@tnotesjs/core 0.1.27 → 0.2.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.
Files changed (71) hide show
  1. package/README.md +2 -1
  2. package/package.json +3 -1
  3. package/templates/sub-repo/.gitattributes +30 -0
  4. package/templates/sub-repo/.github/workflows/deploy.yml +87 -0
  5. package/templates/sub-repo/.vitepress/config.mts +12 -0
  6. package/templates/sub-repo/.vitepress/env.d.ts +10 -0
  7. package/templates/sub-repo/.vitepress/theme/index.ts +12 -0
  8. package/templates/sub-repo/.vscode/settings.json +330 -0
  9. package/templates/sub-repo/.vscode/tnotes.code-snippets +110 -0
  10. package/templates/sub-repo/public/favicon.ico +0 -0
  11. package/templates/sub-repo/public/logo.png +0 -0
  12. package/templates/sub-repo/tsconfig.json +45 -0
  13. package/vitepress/assets/icons/icon__setting_dark.svg +4 -0
  14. package/vitepress/assets/icons/icon__setting_light.svg +4 -0
  15. package/vitepress/assets/icons/index.ts +2 -2
  16. package/vitepress/client/localSearchIndexBridge.ts +24 -0
  17. package/vitepress/components/Discussions/Discussions.vue +1 -1
  18. package/vitepress/components/Footprints/Footprints.vue +90 -25
  19. package/vitepress/components/Layout/CustomSidebar.vue +489 -117
  20. package/vitepress/components/Layout/Layout.vue +5 -0
  21. package/vitepress/components/Layout/NavBarSettingsTrigger.vue +10 -2
  22. package/vitepress/components/Layout/SidebarItems.vue +517 -342
  23. package/vitepress/components/Layout/SidebarNavBefore.vue +1 -50
  24. package/vitepress/components/Layout/SidebarResizeHandle.vue +6 -23
  25. package/vitepress/components/Layout/composables/docLayoutLogic.ts +59 -0
  26. package/vitepress/components/Layout/composables/useDocLayout.test.ts +69 -0
  27. package/vitepress/components/Layout/composables/useDocLayout.ts +128 -0
  28. package/vitepress/components/Layout/composables/useSidebarDrag.ts +514 -0
  29. package/vitepress/components/Layout/composables/useSidebarLayout.ts +25 -8
  30. package/vitepress/components/Layout/composables/useVSCodeIntegration.ts +8 -3
  31. package/vitepress/components/Layout/sidebarCollapsedState.test.ts +183 -0
  32. package/vitepress/components/Layout/sidebarCollapsedState.ts +241 -0
  33. package/vitepress/components/Layout/sidebarDragLogic.test.ts +1146 -0
  34. package/vitepress/components/Layout/sidebarDragLogic.ts +1307 -0
  35. package/vitepress/components/Layout/sidebarHitTest.test.ts +572 -0
  36. package/vitepress/components/Layout/sidebarHitTest.ts +801 -0
  37. package/vitepress/components/Layout/sidebarItemRenderLogic.test.ts +53 -0
  38. package/vitepress/components/Layout/sidebarItemRenderLogic.ts +50 -0
  39. package/vitepress/components/MarkMap/MarkMap.vue +67 -10
  40. package/vitepress/components/Settings/Settings.vue +78 -74
  41. package/vitepress/components/SidebarCard/FolderTreeItems.vue +268 -0
  42. package/vitepress/components/SidebarCard/SidebarCard.vue +125 -274
  43. package/vitepress/components/constants.ts +18 -6
  44. package/vitepress/components/sidebar.data.ts +13 -11
  45. package/vitepress/components/sidebarTreeHelpers.test.ts +142 -0
  46. package/vitepress/components/sidebarTreeHelpers.ts +168 -0
  47. package/vitepress/components/utils/vscodePaths.test.ts +41 -0
  48. package/vitepress/components/utils/vscodePaths.ts +52 -0
  49. package/vitepress/config/index.ts +2 -0
  50. package/vitepress/plugins/localSearchIndexBuilder.ts +209 -0
  51. package/vitepress/plugins/localSearchReindex.test.ts +46 -0
  52. package/vitepress/plugins/localSearchReindexLogic.ts +50 -0
  53. package/vitepress/plugins/localSearchReindexPatch.test.ts +30 -0
  54. package/vitepress/plugins/localSearchReindexPatch.ts +37 -0
  55. package/vitepress/plugins/localSearchReindexPlugin.ts +318 -0
  56. package/vitepress/plugins/sidebarStructurePlugin.ts +209 -63
  57. package/vitepress/theme/index.ts +8 -0
  58. package/vitepress/theme/styles/base.scss +0 -8
  59. package/vitepress/theme/styles/components/markmap.scss +23 -2
  60. package/vitepress/theme/styles/components/swiper.scss +1 -1
  61. package/vitepress/theme/styles/doc-layout.scss +212 -0
  62. package/vitepress/theme/styles/index.scss +3 -0
  63. package/vitepress/theme/styles/layout.scss +60 -10
  64. package/dist/chunk-4KG6RXFS.js +0 -4637
  65. package/dist/chunk-AGSL3VZE.js +0 -193
  66. package/dist/cli/index.js +0 -683
  67. package/dist/index.js +0 -8
  68. package/dist/vitepress/config/index.js +0 -1178
  69. package/vitepress/assets/icons/icon__mindmap.svg +0 -1
  70. package/vitepress/assets/icons/icon__setting.svg +0 -1
  71. package/vitepress/components/SidebarCard/MindMapView.vue +0 -488
package/dist/cli/index.js DELETED
@@ -1,683 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- BaseCommand,
4
- COMMAND_DESCRIPTIONS,
5
- COMMAND_NAMES,
6
- COMMAND_OPTIONS,
7
- FileWatcherService,
8
- GitManager,
9
- GitService,
10
- NoteIndexCache,
11
- NoteManager,
12
- NoteService,
13
- ROOT_CONFIG_PATH,
14
- ROOT_DIR_PATH,
15
- ReadmeService,
16
- RenameNoteCommand,
17
- TimestampService,
18
- UpdateNoteConfigCommand,
19
- VitepressService,
20
- createLogger,
21
- handleError,
22
- logger,
23
- parseArgs,
24
- parseReadmeCompletedNotes,
25
- runCommand
26
- } from "../chunk-4KG6RXFS.js";
27
- import {
28
- ConfigManager
29
- } from "../chunk-AGSL3VZE.js";
30
-
31
- // commands/update/UpdateCommand.ts
32
- import { existsSync, readFileSync, writeFileSync } from "fs";
33
- import { resolve } from "path";
34
- var UpdateCommand = class extends BaseCommand {
35
- constructor() {
36
- super("update");
37
- this.quiet = false;
38
- this.readmeService = ReadmeService.getInstance();
39
- this.noteService = NoteService.getInstance();
40
- }
41
- /**
42
- * 设置 quiet 模式
43
- *
44
- * 在 quiet 模式下,只显示 WARN 级别以上的日志
45
- */
46
- setQuiet(quiet) {
47
- this.quiet = quiet;
48
- if (quiet) {
49
- logger.setLevel(2 /* WARN */);
50
- } else {
51
- logger.setLevel(1 /* INFO */);
52
- }
53
- }
54
- async run() {
55
- await this.updateCurrentRepo();
56
- }
57
- /**
58
- * 更新当前知识库
59
- */
60
- async updateCurrentRepo() {
61
- const startTime = Date.now();
62
- const notes = this.noteService.getAllNotes();
63
- if (!this.quiet) {
64
- this.logger.info("\u6B63\u5728\u4FEE\u6B63\u7B14\u8BB0\u6807\u9898...");
65
- }
66
- const fixedCount = await this.noteService.fixAllNoteTitles(notes);
67
- if (!this.quiet && fixedCount > 0) {
68
- this.logger.success(`\u4FEE\u6B63\u4E86 ${fixedCount} \u4E2A\u7B14\u8BB0\u6807\u9898`);
69
- }
70
- await this.readmeService.updateAllReadmes({ notes });
71
- await this.updateRootItem();
72
- const duration = Date.now() - startTime;
73
- if (this.quiet) {
74
- this.logger.success(`\u77E5\u8BC6\u5E93\u66F4\u65B0\u5B8C\u6210 (${duration}ms)`);
75
- } else {
76
- this.logger.success("\u77E5\u8BC6\u5E93\u66F4\u65B0\u5B8C\u6210");
77
- }
78
- }
79
- /**
80
- * 更新 root_item 配置
81
- * 只更新当前月份的完成笔记数量
82
- */
83
- async updateRootItem() {
84
- try {
85
- const configContent = readFileSync(ROOT_CONFIG_PATH, "utf-8");
86
- const config = JSON.parse(configContent);
87
- const readmePath = resolve(ROOT_DIR_PATH, "README.md");
88
- if (!existsSync(readmePath)) {
89
- throw new Error("\u6839\u76EE\u5F55 README.md \u4E0D\u5B58\u5728");
90
- }
91
- const readmeContent = readFileSync(readmePath, "utf-8");
92
- const { completedCount } = parseReadmeCompletedNotes(readmeContent);
93
- const now = /* @__PURE__ */ new Date();
94
- const yearShort = String(now.getFullYear()).slice(-2);
95
- const monthStr = String(now.getMonth() + 1).padStart(2, "0");
96
- const currentKey = `${yearShort}.${monthStr}`;
97
- const completedNotesCount = {
98
- ...config.root_item.completed_notes_count || {},
99
- [currentKey]: completedCount
100
- };
101
- config.root_item = {
102
- ...config.root_item,
103
- completed_notes_count: completedNotesCount
104
- };
105
- delete config.root_item.completed_notes_count_last_month;
106
- writeFileSync(ROOT_CONFIG_PATH, JSON.stringify(config, null, 2), "utf-8");
107
- if (!this.quiet) {
108
- this.logger.success(
109
- `root_item \u914D\u7F6E\u5DF2\u66F4\u65B0: ${currentKey} \u6708\u5B8C\u6210 ${completedCount} \u7BC7\u7B14\u8BB0`
110
- );
111
- }
112
- } catch (error) {
113
- if (!this.quiet) {
114
- this.logger.error(
115
- `\u66F4\u65B0 root_item \u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`
116
- );
117
- }
118
- throw error;
119
- }
120
- }
121
- };
122
-
123
- // commands/git/PushCommand.ts
124
- var PushCommand = class extends BaseCommand {
125
- constructor() {
126
- super("push");
127
- this.gitManager = new GitManager(ROOT_DIR_PATH);
128
- this.gitService = new GitService();
129
- this.timestampService = new TimestampService();
130
- }
131
- async run() {
132
- try {
133
- this.logger.info("\u68C0\u67E5\u662F\u5426\u6709\u66F4\u6539...");
134
- const status = await this.gitManager.getStatus();
135
- const hasPendingCommits = (status.ahead ?? 0) > 0;
136
- if (!status.hasChanges && !hasPendingCommits) {
137
- this.logger.info("\u6CA1\u6709\u66F4\u6539\u9700\u8981\u63A8\u9001");
138
- return;
139
- }
140
- const force = this.options.force === true;
141
- if (force) {
142
- this.logger.warn("\u4F7F\u7528\u5F3A\u5236\u63A8\u9001\u6A21\u5F0F (--force)");
143
- }
144
- if (status.hasChanges) {
145
- this.logger.info(
146
- `\u68C0\u6D4B\u5230 ${status.files.length} \u4E2A\u53D8\u66F4\u6587\u4EF6\uFF0C\u6B63\u5728\u63D0\u4EA4...`
147
- );
148
- const commitMessage = this.gitService.generateCommitMessage();
149
- await runCommand("git add -A", ROOT_DIR_PATH);
150
- await runCommand(`git commit -m "${commitMessage}"`, ROOT_DIR_PATH);
151
- this.logger.info("\u4FEE\u590D\u7B14\u8BB0\u65F6\u95F4\u6233...");
152
- await this.timestampService.fixAllTimestamps(false);
153
- const afterFixStatus = await runCommand(
154
- "git -c core.quotePath=false status --porcelain",
155
- ROOT_DIR_PATH
156
- );
157
- const hasTimestampChanges = afterFixStatus.split(/\r?\n/).filter(Boolean).some((line) => line.includes(".tnotes.json"));
158
- if (hasTimestampChanges) {
159
- this.logger.info("\u5C06\u65F6\u95F4\u6233\u53D8\u66F4\u5408\u5E76\u5230 commit...");
160
- await runCommand("git add -u", ROOT_DIR_PATH);
161
- await runCommand("git commit --amend --no-edit", ROOT_DIR_PATH);
162
- }
163
- } else {
164
- this.logger.info(`\u68C0\u6D4B\u5230 ${status.ahead} \u4E2A\u672A\u63A8\u9001\u7684\u63D0\u4EA4\uFF0C\u76F4\u63A5\u63A8\u9001...`);
165
- }
166
- this.logger.info("\u6B63\u5728\u63A8\u9001\u5230\u8FDC\u7A0B\u4ED3\u5E93...");
167
- const pushCmd = force ? "git push --force" : "git push";
168
- await runCommand(pushCmd, ROOT_DIR_PATH);
169
- this.logger.success("\u63A8\u9001\u5B8C\u6210");
170
- } catch (error) {
171
- this.logger.error("\u63A8\u9001\u5931\u8D25:", error);
172
- throw error;
173
- }
174
- }
175
- };
176
-
177
- // commands/git/PullCommand.ts
178
- var PullCommand = class extends BaseCommand {
179
- constructor() {
180
- super("pull");
181
- this.gitService = new GitService();
182
- }
183
- async run() {
184
- this.logger.info("\u6B63\u5728\u4ECE\u8FDC\u7A0B\u4ED3\u5E93\u62C9\u53D6...");
185
- await this.gitService.pull();
186
- this.logger.success("\u62C9\u53D6\u5B8C\u6210");
187
- }
188
- };
189
-
190
- // commands/build/BuildCommand.ts
191
- var BuildCommand = class extends BaseCommand {
192
- constructor() {
193
- super("build");
194
- this.vitepressService = new VitepressService();
195
- }
196
- async run() {
197
- this.logger.info("\u5F00\u59CB\u6784\u5EFA\u77E5\u8BC6\u5E93...");
198
- await this.vitepressService.build();
199
- this.logger.success("\u77E5\u8BC6\u5E93\u6784\u5EFA\u5B8C\u6210");
200
- }
201
- };
202
-
203
- // commands/build/PreviewCommand.ts
204
- var PreviewCommand = class extends BaseCommand {
205
- constructor() {
206
- super("preview");
207
- this.vitepressService = new VitepressService();
208
- }
209
- async run() {
210
- this.logger.info("\u542F\u52A8\u9884\u89C8\u670D\u52A1\u5668...");
211
- const pid = await this.vitepressService.preview();
212
- if (pid) {
213
- this.logger.success(`\u9884\u89C8\u670D\u52A1\u5668\u5DF2\u542F\u52A8 (PID: ${pid})`);
214
- } else {
215
- this.logger.error("\u542F\u52A8\u9884\u89C8\u670D\u52A1\u5668\u5931\u8D25");
216
- }
217
- }
218
- };
219
-
220
- // commands/dev/DevCommand.ts
221
- var DevCommand = class extends BaseCommand {
222
- constructor() {
223
- super("dev");
224
- this.configManager = ConfigManager.getInstance();
225
- this.fileWatcherService = new FileWatcherService();
226
- this.noteIndexCache = NoteIndexCache.getInstance();
227
- this.noteManager = NoteManager.getInstance();
228
- this.readmeService = ReadmeService.getInstance();
229
- this.vitepressService = new VitepressService();
230
- }
231
- async run() {
232
- const notes = this.noteManager.scanNotes();
233
- this.logger.info(`\u626B\u63CF\u5230 ${notes.length} \u7BC7\u7B14\u8BB0`);
234
- this.noteIndexCache.initialize(notes);
235
- await this.readmeService.regenerateSidebar(notes);
236
- const result = await this.vitepressService.startServer();
237
- if (result) {
238
- const versionInfo = result.version ? `\uFF08v${result.version}\uFF09` : "";
239
- this.logger.success(
240
- `VitePress \u670D\u52A1${versionInfo}\u5DF2\u5C31\u7EEA\uFF0C\u8017\u65F6\uFF1A${result.elapsed} ms`
241
- );
242
- const watcherStart = Date.now();
243
- this.fileWatcherService.start();
244
- const watcherElapsed = Date.now() - watcherStart;
245
- this.logger.success(`\u6587\u4EF6\u76D1\u542C\u670D\u52A1\u5DF2\u5C31\u7EEA\uFF0C\u8017\u65F6\uFF1A${watcherElapsed} ms`);
246
- const port2 = this.configManager.get("port") || VitepressService.DEFAULT_DEV_PORT;
247
- const repoName2 = this.configManager.get("repoName");
248
- this.logger.info(
249
- `\u672C\u5730\u5F00\u53D1\u670D\u52A1\u5730\u5740\uFF1Ahttp://localhost:${port2}/${repoName2}/`
250
- );
251
- } else {
252
- this.logger.error("\u542F\u52A8\u670D\u52A1\u5668\u5931\u8D25");
253
- }
254
- }
255
- };
256
-
257
- // commands/maintenance/FixTimestampsCommand.ts
258
- var FixTimestampsCommand = class extends BaseCommand {
259
- constructor() {
260
- super("fix-timestamps");
261
- this.timestampService = new TimestampService();
262
- }
263
- async run() {
264
- this.logger.info("\u5F00\u59CB\u4FEE\u590D\u6240\u6709\u7B14\u8BB0\u7684\u65F6\u95F4\u6233...");
265
- this.logger.info("\u{1F4CC} \u6B64\u64CD\u4F5C\u4F1A\u5C06\u6240\u6709\u65F6\u95F4\u6233\u66F4\u65B0\u4E3A git \u771F\u5B9E\u65F6\u95F4");
266
- this.logger.info("");
267
- const result = await this.timestampService.fixAllTimestamps(true);
268
- this.logger.info("");
269
- this.logger.info("\u{1F4CA} \u4FEE\u590D\u7EDF\u8BA1:");
270
- this.logger.info(
271
- ` - \u6839\u914D\u7F6E\u6587\u4EF6: ${result.rootConfigFixed ? "\u5DF2\u4FEE\u590D" : "\u65E0\u9700\u4FEE\u590D"}`
272
- );
273
- this.logger.info(` - \u603B\u7B14\u8BB0\u6570: ${result.total}`);
274
- this.logger.info(` - \u5DF2\u4FEE\u590D: ${result.fixed}`);
275
- this.logger.info(` - \u8DF3\u8FC7: ${result.skipped}`);
276
- this.logger.info("");
277
- if (result.fixed > 0 || result.rootConfigFixed) {
278
- this.logger.success(
279
- `\u2705 \u6210\u529F\u4FEE\u590D ${result.fixed} \u4E2A\u7B14\u8BB0${result.rootConfigFixed ? " + \u6839\u914D\u7F6E\u6587\u4EF6" : ""}\u7684\u65F6\u95F4\u6233\uFF01`
280
- );
281
- this.logger.info("\u{1F4A1} \u63D0\u793A: \u8FD0\u884C pnpm tn:push \u63D0\u4EA4\u66F4\u6539");
282
- } else {
283
- this.logger.success("\u2705 \u6240\u6709\u65F6\u95F4\u6233\u5747\u5DF2\u6B63\u786E\uFF01");
284
- }
285
- }
286
- };
287
-
288
- // commands/misc/HelpCommand.ts
289
- var COMMAND_CATEGORIES = {
290
- \u5F00\u53D1\u548C\u6784\u5EFA: [COMMAND_NAMES.DEV, COMMAND_NAMES.BUILD, COMMAND_NAMES.PREVIEW],
291
- \u5185\u5BB9\u7BA1\u7406: [
292
- COMMAND_NAMES.UPDATE,
293
- COMMAND_NAMES.UPDATE_COMPLETED_COUNT,
294
- COMMAND_NAMES.CREATE_NOTES
295
- ],
296
- "Git \u64CD\u4F5C": [COMMAND_NAMES.PUSH, COMMAND_NAMES.PULL],
297
- \u5176\u4ED6: [COMMAND_NAMES.FIX_TIMESTAMPS, COMMAND_NAMES.HELP]
298
- };
299
- var COMMAND_OPTIONS_INFO = {
300
- [COMMAND_OPTIONS.QUIET]: {
301
- description: "\u9759\u9ED8\u6A21\u5F0F",
302
- applicableTo: "update"
303
- },
304
- [COMMAND_OPTIONS.FORCE]: {
305
- description: "\u5F3A\u5236\u63A8\u9001",
306
- applicableTo: "push"
307
- }
308
- };
309
- var HelpCommand = class extends BaseCommand {
310
- constructor() {
311
- super("help");
312
- this.logger = createLogger("help", {
313
- timestamp: false,
314
- level: process.env.DEBUG ? 0 /* DEBUG */ : 1 /* INFO */
315
- });
316
- }
317
- async run() {
318
- this.logger.info("TNotes \u547D\u4EE4\u884C\u5DE5\u5177");
319
- this.logger.info("");
320
- this.logger.info("\u7528\u6CD5\uFF1Apnpm tn:<command> # \u63A8\u8350");
321
- this.logger.info("\u6216\u8005\uFF1Anpx tsx ./.vitepress/tnotes/index.ts --<command>");
322
- this.logger.info("");
323
- this.logger.info("\u53EF\u7528\u547D\u4EE4\uFF1A");
324
- this.logger.info("");
325
- for (const [category, cmdNames] of Object.entries(COMMAND_CATEGORIES)) {
326
- this.logger.info(` ${category}:`);
327
- for (const cmdName of cmdNames) {
328
- const description = COMMAND_DESCRIPTIONS[cmdName];
329
- const paddingLength = Math.max(25 - cmdName.length, 1);
330
- const padding = " ".repeat(paddingLength);
331
- this.logger.info(` --${cmdName}${padding}${description}`);
332
- }
333
- this.logger.info("");
334
- }
335
- this.logger.info("\u793A\u4F8B\uFF1A");
336
- this.logger.info(" npx tsx ./.vitepress/tnotes/index.ts --dev");
337
- this.logger.info(" pnpm tn:build");
338
- this.logger.info(" pnpm tn:create-notes # \u6279\u91CF\u521B\u5EFA\u7B14\u8BB0");
339
- this.logger.info(" pnpm tn:update");
340
- this.logger.info(
341
- " pnpm tn:update-completed-count # \u751F\u6210\u5F53\u524D\u77E5\u8BC6\u5E93\u6700\u8FD1 12 \u4E2A\u6708\u7684\u5B8C\u6210\u7B14\u8BB0\u6570\u91CF\u7EDF\u8BA1"
342
- );
343
- this.logger.info("");
344
- this.logger.info("\u53C2\u6570\uFF1A");
345
- for (const [option, info] of Object.entries(COMMAND_OPTIONS_INFO)) {
346
- const paddingLength = Math.max(13 - option.length, 1);
347
- const padding = " ".repeat(paddingLength);
348
- this.logger.info(
349
- ` --${option}${padding}${info.description} (\u9002\u7528\u4E8E ${info.applicableTo})`
350
- );
351
- }
352
- this.logger.info("");
353
- this.logger.info("\u73AF\u5883\u53D8\u91CF\uFF1A");
354
- this.logger.info(" DEBUG=1 \u542F\u7528\u8C03\u8BD5\u6A21\u5F0F\uFF0C\u663E\u793A\u8BE6\u7EC6\u65E5\u5FD7");
355
- this.logger.info("");
356
- this.logger.info("\u66F4\u591A\u4FE1\u606F\u8BF7\u67E5\u770B: .vitepress/tnotes/README.md");
357
- }
358
- };
359
-
360
- // commands/note/CreateNoteCommand.ts
361
- import { createInterface } from "readline";
362
- import { v4 as uuidv4 } from "uuid";
363
- var CreateNoteCommand = class extends BaseCommand {
364
- constructor() {
365
- super("create-notes");
366
- this.noteService = NoteService.getInstance();
367
- this.readmeService = ReadmeService.getInstance();
368
- }
369
- async run() {
370
- this.logger.info("\u521B\u5EFA\u65B0\u7B14\u8BB0...");
371
- const count = await this.promptForCount();
372
- let successCount = 0;
373
- let failCount = 0;
374
- const createdNotes = [];
375
- const existingNotes = this.noteService.getAllNotes();
376
- const usedIndexes = /* @__PURE__ */ new Set();
377
- for (const note of existingNotes) {
378
- const index = parseInt(note.index, 10);
379
- if (!isNaN(index) && index >= 1 && index <= 9999) {
380
- usedIndexes.add(index);
381
- }
382
- }
383
- for (let i = 1; i <= count; i++) {
384
- try {
385
- let title;
386
- if (count === 1) {
387
- title = await this.promptForTitle();
388
- } else {
389
- title = `new`;
390
- this.logger.info(`[${i}/${count}] \u521B\u5EFA\u7B14\u8BB0: ${title}`);
391
- }
392
- const configId = uuidv4();
393
- const note = await this.noteService.createNote({
394
- title: title || `new`,
395
- enableDiscussions: false,
396
- configId,
397
- // 传递 UUID 作为配置 ID(跨知识库唯一)
398
- usedIndexes
399
- // 传入已使用编号集合,避免重复扫描
400
- });
401
- const newIndex = parseInt(note.index, 10);
402
- if (!isNaN(newIndex)) {
403
- usedIndexes.add(newIndex);
404
- }
405
- createdNotes.push(note.dirName);
406
- successCount++;
407
- if (count === 1) {
408
- this.logger.success(`\u7B14\u8BB0\u521B\u5EFA\u6210\u529F: ${note.dirName}`);
409
- this.logger.info(`\u7B14\u8BB0\u8DEF\u5F84: ${note.path}`);
410
- this.logger.info(`\u7B14\u8BB0\u7F16\u53F7: ${note.index}`);
411
- this.logger.info(`\u914D\u7F6EID: ${configId}`);
412
- } else {
413
- this.logger.success(`[${i}/${count}] \u521B\u5EFA\u6210\u529F: ${note.dirName}`);
414
- }
415
- } catch (error) {
416
- failCount++;
417
- this.logger.error(`[${i}/${count}] \u521B\u5EFA\u5931\u8D25`, error);
418
- }
419
- }
420
- if (count > 1) {
421
- console.log("");
422
- this.logger.info(
423
- `\u{1F4CA} \u521B\u5EFA\u5B8C\u6210: \u6210\u529F ${successCount} \u7BC7, \u5931\u8D25 ${failCount} \u7BC7`
424
- );
425
- }
426
- if (successCount > 0) {
427
- this.logger.info("\u6B63\u5728\u66F4\u65B0\u77E5\u8BC6\u5E93\u7D22\u5F15...");
428
- await this.readmeService.updateAllReadmes();
429
- this.logger.success("\u77E5\u8BC6\u5E93\u7D22\u5F15\u66F4\u65B0\u5B8C\u6210");
430
- }
431
- }
432
- /**
433
- * 提示用户输入要创建的笔记数量
434
- */
435
- async promptForCount() {
436
- const rl = createInterface({
437
- input: process.stdin,
438
- output: process.stdout
439
- });
440
- return new Promise((resolve2) => {
441
- rl.question("\n\u{1F4DD} \u8BF7\u8F93\u5165\u8981\u521B\u5EFA\u7684\u7B14\u8BB0\u6570\u91CF\uFF08\u9ED8\u8BA4\u4E3A 1\uFF09: ", (answer) => {
442
- rl.close();
443
- const trimmed = answer.trim();
444
- if (!trimmed) {
445
- this.logger.info("\u4F7F\u7528\u9ED8\u8BA4\u6570\u91CF: 1");
446
- resolve2(1);
447
- return;
448
- }
449
- const num = parseInt(trimmed, 10);
450
- if (isNaN(num) || num < 1 || !Number.isInteger(num)) {
451
- this.logger.warn(`\u8F93\u5165 "${trimmed}" \u4E0D\u662F\u6709\u6548\u7684\u6B63\u6574\u6570\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u503C: 1`);
452
- resolve2(1);
453
- return;
454
- }
455
- this.logger.info(`\u5C06\u521B\u5EFA ${num} \u7BC7\u7B14\u8BB0`);
456
- resolve2(num);
457
- });
458
- });
459
- }
460
- /**
461
- * 提示用户输入笔记标题
462
- */
463
- async promptForTitle() {
464
- const rl = createInterface({
465
- input: process.stdin,
466
- output: process.stdout
467
- });
468
- return new Promise((resolve2) => {
469
- rl.question("\u8BF7\u8F93\u5165\u7B14\u8BB0\u6807\u9898: ", (answer) => {
470
- rl.close();
471
- resolve2(answer.trim());
472
- });
473
- });
474
- }
475
- };
476
-
477
- // commands/update-completed-count/UpdateCompletedCountCommand.ts
478
- import { execSync } from "child_process";
479
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
480
- var UpdateCompletedCountCommand = class extends BaseCommand {
481
- constructor() {
482
- super("update-completed-count");
483
- }
484
- async run() {
485
- await this.updateCurrentRepo();
486
- }
487
- /**
488
- * 更新当前知识库
489
- */
490
- async updateCurrentRepo() {
491
- const startTime = Date.now();
492
- try {
493
- const configContent = readFileSync2(ROOT_CONFIG_PATH, "utf-8");
494
- const config = JSON.parse(configContent);
495
- this.logger.info("\u5F00\u59CB\u66F4\u65B0\u5B8C\u6210\u7B14\u8BB0\u6570\u91CF\u5386\u53F2\u8BB0\u5F55...");
496
- const completedNotesCountHistory = await this.getCompletedNotesCountHistory(
497
- config.root_item.created_at ?? Date.now()
498
- );
499
- config.root_item = {
500
- ...config.root_item,
501
- completed_notes_count: completedNotesCountHistory
502
- };
503
- writeFileSync2(ROOT_CONFIG_PATH, JSON.stringify(config, null, 2), "utf-8");
504
- const duration = Date.now() - startTime;
505
- const monthKeys = Object.keys(completedNotesCountHistory);
506
- const currentKey = monthKeys[monthKeys.length - 1];
507
- const currentCount = completedNotesCountHistory[currentKey] || 0;
508
- this.logger.success(
509
- `\u5386\u53F2\u6570\u636E\u66F4\u65B0\u5B8C\u6210: \u5171 ${monthKeys.length} \u4E2A\u6708, \u5F53\u524D ${currentKey} \u6708\u5B8C\u6210 ${currentCount} \u7BC7\u7B14\u8BB0 (${duration}ms)`
510
- );
511
- } catch (error) {
512
- this.logger.error(
513
- `\u66F4\u65B0\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`
514
- );
515
- throw error;
516
- }
517
- }
518
- /**
519
- * 获取历史每个月的 completed_notes_count(最近12个月)
520
- *
521
- * 逻辑:
522
- * 1. 计算最近12个月的范围(当前月份往前推11个月)
523
- * 2. 遍历这12个月,从 Git 历史中读取 README.md
524
- * 3. 解析 README.md 获取完成笔记数量
525
- * 4. 如果知识库创建时间在这12个月内,之前的月份补0
526
- * 5. 返回对象 { '25.01': 0, '25.02': 1, ..., '25.12': 15 }
527
- */
528
- async getCompletedNotesCountHistory(createdAt) {
529
- try {
530
- const now = /* @__PURE__ */ new Date();
531
- const currentYear = now.getFullYear();
532
- const currentMonth = now.getMonth();
533
- let firstYear = currentYear;
534
- let firstMonth = currentMonth - 11;
535
- if (firstMonth < 0) {
536
- firstYear = currentYear - 1;
537
- firstMonth = 12 + firstMonth;
538
- }
539
- const createdDate = new Date(createdAt);
540
- const createdYear = createdDate.getFullYear();
541
- const createdMonth = createdDate.getMonth();
542
- const result = {};
543
- let prevCount = 0;
544
- for (let i = 0; i < 12; i++) {
545
- const targetYear = firstYear + Math.floor((firstMonth + i) / 12);
546
- const targetMonth = (firstMonth + i) % 12;
547
- const yearShort = String(targetYear).slice(-2);
548
- const monthStr = String(targetMonth + 1).padStart(2, "0");
549
- const key = `${yearShort}.${monthStr}`;
550
- const isBeforeCreation = targetYear < createdYear || targetYear === createdYear && targetMonth < createdMonth;
551
- if (isBeforeCreation) {
552
- result[key] = 0;
553
- prevCount = 0;
554
- this.logger.info(`\u2713 ${key}: 0 \u7BC7\uFF08\u65E9\u4E8E\u521B\u5EFA\u65F6\u95F4\uFF09`);
555
- } else {
556
- try {
557
- const count = await this.getMonthCompletedCount(
558
- targetYear,
559
- targetMonth,
560
- prevCount
561
- );
562
- result[key] = count;
563
- prevCount = count;
564
- this.logger.info(`\u2713 ${key}: ${count} \u7BC7`);
565
- } catch (error) {
566
- result[key] = prevCount;
567
- this.logger.warn(`${key}: \u65E0\u6570\u636E\uFF0C\u4F7F\u7528 ${prevCount}\uFF08\u4E0A\u6708\u503C\uFF09`);
568
- }
569
- }
570
- }
571
- return result;
572
- } catch (error) {
573
- this.logger.error(
574
- `\u83B7\u53D6\u5386\u53F2\u6570\u636E\u5931\u8D25: ${error instanceof Error ? error.message : String(error)}`
575
- );
576
- return {};
577
- }
578
- }
579
- /**
580
- * 获取指定月份的完成笔记数量
581
- * @param year - 年份
582
- * @param month - 月份 (0-11)
583
- * @param fallbackCount - 回退值(如果该月没有数据)
584
- * @returns 完成笔记数量
585
- */
586
- async getMonthCompletedCount(year, month, fallbackCount = 0) {
587
- const lastDayOfMonth = new Date(year, month + 1, 0, 23, 59, 59);
588
- const yearStr = lastDayOfMonth.getFullYear();
589
- const monthStr = String(lastDayOfMonth.getMonth() + 1).padStart(2, "0");
590
- const dayStr = String(lastDayOfMonth.getDate()).padStart(2, "0");
591
- const untilDate = `${yearStr}-${monthStr}-${dayStr} 23:59:59 +0800`;
592
- const commitHash = execSync(
593
- `git log --until="${untilDate}" --format=%H -1 -- README.md`,
594
- {
595
- cwd: ROOT_DIR_PATH,
596
- encoding: "utf-8"
597
- }
598
- ).trim();
599
- if (!commitHash) {
600
- return fallbackCount;
601
- }
602
- let readmeContent;
603
- try {
604
- readmeContent = execSync(`git show ${commitHash}:README.md`, {
605
- cwd: ROOT_DIR_PATH,
606
- encoding: "utf-8"
607
- });
608
- } catch (error) {
609
- return fallbackCount;
610
- }
611
- const { completedCount } = parseReadmeCompletedNotes(readmeContent);
612
- return completedCount;
613
- }
614
- };
615
-
616
- // commands/registry.ts
617
- var commandFactories = {
618
- "build": () => new BuildCommand(),
619
- "create-notes": () => new CreateNoteCommand(),
620
- "dev": () => new DevCommand(),
621
- "fix-timestamps": () => new FixTimestampsCommand(),
622
- "help": () => new HelpCommand(),
623
- "preview": () => new PreviewCommand(),
624
- "pull": () => new PullCommand(),
625
- "push": () => new PushCommand(),
626
- "rename-note": () => new RenameNoteCommand(),
627
- "update-completed-count": () => new UpdateCompletedCountCommand(),
628
- "update-note-config": () => new UpdateNoteConfigCommand(),
629
- "update": () => new UpdateCommand()
630
- };
631
- var commandCache = /* @__PURE__ */ new Map();
632
- function getCommand(name) {
633
- if (!commandFactories[name]) return void 0;
634
- if (!commandCache.has(name)) commandCache.set(name, commandFactories[name]());
635
- return commandCache.get(name);
636
- }
637
-
638
- // index.ts
639
- (async () => {
640
- try {
641
- const args = parseArgs(process.argv.slice(2));
642
- const commandName = Object.keys(args).find(
643
- (key) => key !== "_" && args[key] === true
644
- );
645
- const command = commandName ? getCommand(commandName) : null;
646
- if (!command) {
647
- const logger2 = createLogger("command-not-found", {
648
- timestamp: false
649
- });
650
- console.log(`
651
- ${"-".repeat(66)}
652
- `);
653
- if (commandName) {
654
- logger2.warn(`\u672A\u627E\u5230\u547D\u4EE4\uFF1A${commandName}`);
655
- logger2.info(`\u8BF7\u68C0\u67E5\u547D\u4EE4\u540D\u662F\u5426\u6B63\u786E\uFF01`);
656
- } else {
657
- logger2.warn(`\u672A\u68C0\u6D4B\u5230\u547D\u4EE4\u540D\uFF0C\u8BF7\u68C0\u67E5\u547D\u4EE4\u8F93\u5165\u662F\u5426\u6B63\u786E`);
658
- logger2.info(`\u793A\u4F8B\uFF1A`);
659
- logger2.info(`pnpm tn:<\u547D\u4EE4\u540D>`);
660
- logger2.info(`npx tsx ./.vitepress/tnotes/index.ts --<\u547D\u4EE4\u540D>`);
661
- }
662
- console.log(`
663
- ${"-".repeat(66)}
664
- `);
665
- const helpCommand = getCommand(COMMAND_NAMES.HELP);
666
- if (helpCommand) {
667
- console.log("\n\u6B63\u5728\u6267\u884C pnpm tn:help \u6253\u5370\u5E2E\u52A9\u4FE1\u606F...\n");
668
- await helpCommand.execute();
669
- }
670
- return;
671
- }
672
- if (commandName === COMMAND_NAMES.UPDATE) {
673
- const cmd = command;
674
- if (args.quiet) cmd.setQuiet(true);
675
- } else if (commandName === COMMAND_NAMES.PUSH) {
676
- const cmd = command;
677
- if (args.force) cmd.setOptions({ force: true });
678
- }
679
- await command.execute();
680
- } catch (error) {
681
- handleError(error, true);
682
- }
683
- })();
package/dist/index.js DELETED
@@ -1,8 +0,0 @@
1
- import {
2
- ConfigManager,
3
- getConfigManager
4
- } from "./chunk-AGSL3VZE.js";
5
- export {
6
- ConfigManager,
7
- getConfigManager
8
- };