@tnotesjs/core 0.2.1 → 0.3.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 (86) hide show
  1. package/README.md +0 -1
  2. package/config/ConfigManager.ts +137 -0
  3. package/config/constants.ts +121 -0
  4. package/config/defaultConfig.ts +33 -4
  5. package/config/index.ts +31 -0
  6. package/config/templates.ts +49 -0
  7. package/core/GitManager.ts +513 -0
  8. package/core/NoteIndexCache.ts +200 -0
  9. package/core/NoteManager.ts +395 -0
  10. package/core/ProcessManager.ts +180 -0
  11. package/core/ReadmeGenerator.ts +215 -0
  12. package/core/TocGenerator.ts +212 -0
  13. package/core/index.ts +11 -0
  14. package/dist/{chunk-5Y5IYS6C.js → chunk-UJG3UU5X.js} +21 -5
  15. package/dist/{chunk-5QN44ES5.js → chunk-XCWFZLER.js} +48 -368
  16. package/dist/cli/index.js +26 -78
  17. package/dist/index.js +1 -1
  18. package/dist/vitepress/config/index.js +2 -2
  19. package/package.json +5 -2
  20. package/services/file-watcher/configChangeHandler.ts +64 -0
  21. package/services/file-watcher/eventScheduler.ts +179 -0
  22. package/services/file-watcher/folderChangeHandler.ts +325 -0
  23. package/services/file-watcher/fsWatcherAdapter.ts +128 -0
  24. package/services/file-watcher/globalUpdateCoordinator.ts +60 -0
  25. package/services/file-watcher/index.ts +7 -0
  26. package/services/file-watcher/internal.ts +79 -0
  27. package/services/file-watcher/readmeChangeHandler.ts +28 -0
  28. package/services/file-watcher/renameDetector.ts +120 -0
  29. package/services/file-watcher/service.ts +352 -0
  30. package/services/file-watcher/watchState.ts +194 -0
  31. package/services/git/index.ts +7 -0
  32. package/services/git/service.ts +114 -0
  33. package/services/index.ts +14 -0
  34. package/services/init-sub-repo/index.ts +2 -0
  35. package/services/init-sub-repo/initSubRepoLogic.test.ts +162 -0
  36. package/services/init-sub-repo/initSubRepoLogic.ts +303 -0
  37. package/services/init-sub-repo/service.ts +101 -0
  38. package/services/note/index.ts +7 -0
  39. package/services/note/service.ts +361 -0
  40. package/services/readme/index.ts +7 -0
  41. package/services/readme/service.ts +761 -0
  42. package/services/toc/index.ts +5 -0
  43. package/services/toc/moveTocInside.test.ts +73 -0
  44. package/services/toc/service.ts +759 -0
  45. package/services/vitepress/index.ts +7 -0
  46. package/services/vitepress/service.ts +339 -0
  47. package/types/config.ts +0 -3
  48. package/types/note.ts +0 -2
  49. package/utils/errorHandler.ts +174 -0
  50. package/utils/file.ts +17 -0
  51. package/utils/genHierarchicalSidebar.ts +69 -0
  52. package/utils/generateAnchor.ts +24 -0
  53. package/utils/getChangedIds.ts +35 -0
  54. package/utils/index.ts +71 -0
  55. package/utils/logger.ts +231 -0
  56. package/utils/markdown.ts +75 -0
  57. package/utils/migrateReadmeToToc.test.ts +111 -0
  58. package/utils/migrateReadmeToToc.ts +135 -0
  59. package/utils/parseArgs.ts +90 -0
  60. package/utils/parseReadmeCompletedNotes.test.ts +90 -0
  61. package/utils/parseReadmeCompletedNotes.ts +108 -0
  62. package/utils/portUtils.ts +113 -0
  63. package/utils/readmeHelpers.ts +190 -0
  64. package/utils/runCommand.ts +29 -0
  65. package/utils/tocHelpers.test.ts +278 -0
  66. package/utils/tocHelpers.ts +855 -0
  67. package/utils/tocNodeId.test.ts +60 -0
  68. package/utils/tocNodeId.ts +97 -0
  69. package/utils/validators.ts +102 -0
  70. package/vitepress/assets/icons/icon__cursor.svg +4 -0
  71. package/vitepress/assets/icons/index.ts +1 -0
  72. package/vitepress/components/Layout/AboutPanel.vue +0 -24
  73. package/vitepress/components/Layout/DocBeforeControls.vue +6 -14
  74. package/vitepress/components/Layout/DocFooter.vue +3 -3
  75. package/vitepress/components/Layout/Layout.vue +0 -30
  76. package/vitepress/components/Layout/composables/useVSCodeIntegration.ts +20 -11
  77. package/vitepress/components/Layout/homeReadme.data.ts +0 -48
  78. package/vitepress/components/MarkMap/MarkMap.vue +6 -13
  79. package/vitepress/components/Settings/Settings.vue +76 -73
  80. package/vitepress/components/SidebarCard/FolderTreeItems.vue +16 -6
  81. package/vitepress/components/SidebarCard/SidebarCard.vue +21 -27
  82. package/vitepress/components/composables/useLocalIde.ts +83 -0
  83. package/vitepress/components/constants.ts +5 -6
  84. package/vitepress/components/utils/vscodePaths.test.ts +22 -0
  85. package/vitepress/components/utils/vscodePaths.ts +24 -2
  86. package/vitepress/theme/styles/doc-layout.scss +4 -4
@@ -2,7 +2,7 @@ import {
2
2
  ConfigManager,
3
3
  getConfigManager,
4
4
  getDefaultConfig
5
- } from "./chunk-5Y5IYS6C.js";
5
+ } from "./chunk-UJG3UU5X.js";
6
6
 
7
7
  // utils/errorHandler.ts
8
8
  var TNotesError = class _TNotesError extends Error {
@@ -1320,9 +1320,7 @@ var NoteManager = class _NoteManager {
1320
1320
  "category",
1321
1321
  "enableDiscussions",
1322
1322
  "description",
1323
- "id",
1324
- "created_at",
1325
- "updated_at"
1323
+ "id"
1326
1324
  ];
1327
1325
  }
1328
1326
  static {
@@ -1336,6 +1334,13 @@ var NoteManager = class _NoteManager {
1336
1334
  description: ""
1337
1335
  };
1338
1336
  }
1337
+ static {
1338
+ /** 已废弃、写回时需剥离的笔记配置字段 */
1339
+ this.DEPRECATED_CONFIG_FIELDS = [
1340
+ "created_at",
1341
+ "updated_at"
1342
+ ];
1343
+ }
1339
1344
  static {
1340
1345
  /** 必需字段(不能缺失) */
1341
1346
  this.REQUIRED_FIELDS = ["id"];
@@ -1355,6 +1360,7 @@ var NoteManager = class _NoteManager {
1355
1360
  return null;
1356
1361
  }
1357
1362
  let needsUpdate = false;
1363
+ const configRecord = config2;
1358
1364
  for (const field of _NoteManager.REQUIRED_FIELDS) {
1359
1365
  if (!config2[field]) {
1360
1366
  return null;
@@ -1364,26 +1370,17 @@ var NoteManager = class _NoteManager {
1364
1370
  _NoteManager.DEFAULT_CONFIG_FIELDS
1365
1371
  )) {
1366
1372
  if (!(key in config2)) {
1367
- ;
1368
- config2[key] = defaultValue;
1373
+ configRecord[key] = defaultValue;
1369
1374
  needsUpdate = true;
1370
1375
  logger.info(`\u8865\u5145\u7F3A\u5931\u5B57\u6BB5 "${key}": ${configPath}`);
1371
1376
  }
1372
1377
  }
1373
- const now = Date.now();
1374
- if (!config2.created_at) {
1375
- config2.created_at = now;
1376
- needsUpdate = true;
1377
- logger.info(
1378
- `\u68C0\u6D4B\u5230 ${configPath} \u7F3A\u5931 created_at \u5B57\u6BB5\uFF0C\u8BF7\u6267\u884C tn:fix-timestamps \u6821\u51C6\u4E3A\u7B14\u8BB0\u9996\u6B21 git commit \u7684\u65F6\u95F4\uFF09`
1379
- );
1380
- }
1381
- if (!config2.updated_at) {
1382
- config2.updated_at = now;
1383
- needsUpdate = true;
1384
- logger.info(
1385
- `\u68C0\u6D4B\u5230 ${configPath} \u7F3A\u5931 updated_at \u5B57\u6BB5\uFF0C\u8BF7\u6267\u884C tn:fix-timestamps \u6821\u51C6\u4E3A\u7B14\u8BB0\u6700\u540E\u4E00\u6B21 git commit \u7684\u65F6\u95F4\uFF09`
1386
- );
1378
+ for (const key of _NoteManager.DEPRECATED_CONFIG_FIELDS) {
1379
+ if (key in configRecord) {
1380
+ delete configRecord[key];
1381
+ needsUpdate = true;
1382
+ logger.info(`\u79FB\u9664\u5E9F\u5F03\u5B57\u6BB5 "${key}": ${configPath}`);
1383
+ }
1387
1384
  }
1388
1385
  const sortedConfig = this.sortConfigKeys(config2);
1389
1386
  if (needsUpdate) {
@@ -1393,18 +1390,13 @@ var NoteManager = class _NoteManager {
1393
1390
  return sortedConfig;
1394
1391
  }
1395
1392
  /**
1396
- * 按指定顺序排序配置对象的键
1393
+ * 按指定顺序排序配置对象的键(仅保留已知字段,丢弃废弃/未知字段)
1397
1394
  */
1398
1395
  sortConfigKeys(config2) {
1399
1396
  const configRecord = config2;
1400
1397
  const sorted = {};
1401
1398
  for (const key of _NoteManager.FIELD_ORDER) {
1402
- if (key in config2) {
1403
- sorted[key] = configRecord[key];
1404
- }
1405
- }
1406
- for (const key of Object.keys(config2)) {
1407
- if (!(key in sorted)) {
1399
+ if (key in configRecord) {
1408
1400
  sorted[key] = configRecord[key];
1409
1401
  }
1410
1402
  }
@@ -1467,7 +1459,6 @@ var NoteManager = class _NoteManager {
1467
1459
  if (!this.validateConfig(config2)) {
1468
1460
  throw new Error(`Invalid config for note: ${noteInfo.dirName}`);
1469
1461
  }
1470
- config2.updated_at = Date.now();
1471
1462
  this.writeNoteConfig(noteInfo.configPath, config2);
1472
1463
  logger.info(`Updated config for note: ${noteInfo.dirName}`);
1473
1464
  }
@@ -1649,7 +1640,6 @@ var COMMAND_NAMES = {
1649
1640
  BUILD: "build",
1650
1641
  CREATE_NOTES: "create-notes",
1651
1642
  DEV: "dev",
1652
- FIX_TIMESTAMPS: "fix-timestamps",
1653
1643
  HELP: "help",
1654
1644
  PREVIEW: "preview",
1655
1645
  PULL: "pull",
@@ -1672,7 +1662,6 @@ var COMMAND_DESCRIPTIONS = {
1672
1662
  [COMMAND_NAMES.CREATE_NOTES]: "\u65B0\u5EFA\u7B14\u8BB0\uFF08\u652F\u6301\u6279\u91CF\u521B\u5EFA\uFF09",
1673
1663
  [COMMAND_NAMES.PUSH]: "\u5C06\u77E5\u8BC6\u5E93\u63A8\u9001\u5230 GitHub",
1674
1664
  [COMMAND_NAMES.PULL]: "\u5C06 GitHub \u7684\u77E5\u8BC6\u5E93\u62C9\u4E0B\u6765",
1675
- [COMMAND_NAMES.FIX_TIMESTAMPS]: "\u4FEE\u590D\u6240\u6709\u7B14\u8BB0\u7684\u65F6\u95F4\u6233\uFF08\u57FA\u4E8E git \u5386\u53F2\uFF09",
1676
1665
  [COMMAND_NAMES.UPDATE_NOTE_CONFIG]: "\u66F4\u65B0\u7B14\u8BB0\u914D\u7F6E\u6587\u4EF6",
1677
1666
  [COMMAND_NAMES.RENAME_NOTE]: "\u91CD\u547D\u540D\u7B14\u8BB0",
1678
1667
  [COMMAND_NAMES.HELP]: "\u663E\u793A\u5E2E\u52A9\u4FE1\u606F"
@@ -1779,7 +1768,9 @@ var NoteIndexCache = class _NoteIndexCache {
1779
1768
  return;
1780
1769
  }
1781
1770
  Object.assign(item.noteConfig, configUpdates);
1782
- item.noteConfig.updated_at = Date.now();
1771
+ const noteConfigRecord = item.noteConfig;
1772
+ delete noteConfigRecord.created_at;
1773
+ delete noteConfigRecord.updated_at;
1783
1774
  logger.debug(`\u66F4\u65B0\u7B14\u8BB0\u914D\u7F6E: ${noteIndex}`, configUpdates);
1784
1775
  }
1785
1776
  /**
@@ -1947,7 +1938,6 @@ var NoteService = class _NoteService {
1947
1938
  done: false,
1948
1939
  category,
1949
1940
  enableDiscussions
1950
- // created_at / updated_at 由 tn:push 时 fix-timestamps 自动写入
1951
1941
  };
1952
1942
  this.noteManager.writeNoteConfig(configPath, config2);
1953
1943
  const noteInfo = {
@@ -4987,314 +4977,6 @@ var GitService = class {
4987
4977
  }
4988
4978
  };
4989
4979
 
4990
- // services/timestamp/service.ts
4991
- import { execSync as execSync3 } from "child_process";
4992
- import {
4993
- existsSync as existsSync8,
4994
- readFileSync as readFileSync7,
4995
- writeFileSync as writeFileSync6,
4996
- readdirSync as readdirSync3,
4997
- statSync as statSync2
4998
- } from "fs";
4999
- import { join as join8 } from "path";
5000
- var BIRTH_DATE = (/* @__PURE__ */ new Date("1999-06-29T00:00:00+08:00")).getTime();
5001
- var TimestampService = class {
5002
- constructor() {
5003
- this.noteManager = NoteManager.getInstance();
5004
- }
5005
- /**
5006
- * 批量获取所有笔记 README.md 的 git 时间戳
5007
- * 只执行 2 次 git log,构建 filePath → {created_at, updated_at} 的映射
5008
- *
5009
- * - 第 1 次:git log --name-only --format=... --diff-filter=A
5010
- * 获取每个文件的首次提交时间(created_at)
5011
- * - 第 2 次:git log --name-only --format=...
5012
- * 获取每个文件的最后修改时间(updated_at)
5013
- */
5014
- buildGitTimestampMap() {
5015
- const createdMap = /* @__PURE__ */ new Map();
5016
- const updatedMap = /* @__PURE__ */ new Map();
5017
- try {
5018
- const createdRaw = execSync3(
5019
- `git log --name-only --format="---COMMIT---%ct" --diff-filter=A -- "notes/*/README.md"`,
5020
- {
5021
- cwd: ROOT_DIR_PATH,
5022
- encoding: "utf-8",
5023
- maxBuffer: 100 * 1024 * 1024,
5024
- stdio: ["pipe", "pipe", "ignore"]
5025
- }
5026
- );
5027
- let currentTimestamp = 0;
5028
- for (const line of createdRaw.split(/\r?\n/)) {
5029
- if (line.startsWith("---COMMIT---")) {
5030
- currentTimestamp = parseInt(line.slice(12)) * 1e3;
5031
- } else if (line.trim() && currentTimestamp) {
5032
- createdMap.set(line.trim(), currentTimestamp);
5033
- }
5034
- }
5035
- const updatedRaw = execSync3(
5036
- `git log --name-only --format="---COMMIT---%ct" -- "notes/*/README.md"`,
5037
- {
5038
- cwd: ROOT_DIR_PATH,
5039
- encoding: "utf-8",
5040
- maxBuffer: 100 * 1024 * 1024,
5041
- stdio: ["pipe", "pipe", "ignore"]
5042
- }
5043
- );
5044
- currentTimestamp = 0;
5045
- for (const line of updatedRaw.split(/\r?\n/)) {
5046
- if (line.startsWith("---COMMIT---")) {
5047
- currentTimestamp = parseInt(line.slice(12)) * 1e3;
5048
- } else if (line.trim() && currentTimestamp) {
5049
- if (!updatedMap.has(line.trim())) {
5050
- updatedMap.set(line.trim(), currentTimestamp);
5051
- }
5052
- }
5053
- }
5054
- } catch (error) {
5055
- logger.error("\u6279\u91CF\u83B7\u53D6 git \u65F6\u95F4\u6233\u5931\u8D25", error);
5056
- }
5057
- const result = /* @__PURE__ */ new Map();
5058
- for (const [file, created_at] of createdMap) {
5059
- const updated_at = updatedMap.get(file) ?? created_at;
5060
- result.set(file, { created_at, updated_at });
5061
- }
5062
- for (const [file, updated_at] of updatedMap) {
5063
- if (!result.has(file)) {
5064
- result.set(file, { created_at: updated_at, updated_at });
5065
- }
5066
- }
5067
- return result;
5068
- }
5069
- /**
5070
- * 从 git 获取文件的创建时间和最后修改时间
5071
- * @param noteDirPath - 笔记目录路径
5072
- * @returns 时间戳对象,包含 created_at 和 updated_at
5073
- */
5074
- getGitTimestamps(noteDirPath) {
5075
- try {
5076
- const readmePath = join8(noteDirPath, "README.md");
5077
- const createdAtOutput = execSync3(
5078
- `git log --diff-filter=A --follow --format=%ct -- "${readmePath}"`,
5079
- {
5080
- cwd: ROOT_DIR_PATH,
5081
- encoding: "utf-8",
5082
- stdio: ["pipe", "pipe", "ignore"]
5083
- }
5084
- ).split(/\r?\n/).filter(Boolean).pop();
5085
- const updatedAtOutput = execSync3(
5086
- `git log -1 --format=%ct -- "${readmePath}"`,
5087
- {
5088
- cwd: ROOT_DIR_PATH,
5089
- encoding: "utf-8",
5090
- stdio: ["pipe", "pipe", "ignore"]
5091
- }
5092
- ).trim();
5093
- if (!createdAtOutput || !updatedAtOutput) {
5094
- return null;
5095
- }
5096
- return {
5097
- created_at: parseInt(createdAtOutput) * 1e3,
5098
- // 转换为毫秒
5099
- updated_at: parseInt(updatedAtOutput) * 1e3
5100
- };
5101
- } catch (error) {
5102
- logger.debug?.(`getGitTimestamps failed: ${noteDirPath}`, error);
5103
- return null;
5104
- }
5105
- }
5106
- /**
5107
- * 修复单个笔记的时间戳
5108
- * @param noteDir - 笔记目录名
5109
- * @param forceUpdate - 是否强制更新(忽略现有值)
5110
- * @param timestampMap - 预构建的时间戳映射(批量模式传入,避免逐个 git log)
5111
- * @returns 是否进行了修复
5112
- */
5113
- fixNoteTimestamps(noteDir, forceUpdate = false, timestampMap) {
5114
- const configPath = join8(NOTES_DIR_PATH, noteDir, ".tnotes.json");
5115
- if (!existsSync8(configPath)) {
5116
- return false;
5117
- }
5118
- try {
5119
- const configContent = readFileSync7(configPath, "utf-8");
5120
- const config2 = JSON.parse(configContent);
5121
- const readmeRelPath = `notes/${noteDir}/README.md`;
5122
- const timestamps = timestampMap ? timestampMap.get(readmeRelPath) ?? null : this.getGitTimestamps(join8(NOTES_DIR_PATH, noteDir));
5123
- if (!timestamps) {
5124
- return false;
5125
- }
5126
- let modified = false;
5127
- if (forceUpdate || !config2.created_at || config2.created_at !== timestamps.created_at) {
5128
- config2.created_at = timestamps.created_at;
5129
- modified = true;
5130
- }
5131
- if (forceUpdate) {
5132
- if (config2.updated_at !== timestamps.updated_at) {
5133
- config2.updated_at = timestamps.updated_at;
5134
- modified = true;
5135
- }
5136
- } else {
5137
- if (!config2.updated_at) {
5138
- config2.updated_at = timestamps.updated_at;
5139
- modified = true;
5140
- } else if (timestamps.updated_at > config2.updated_at) {
5141
- config2.updated_at = timestamps.updated_at;
5142
- modified = true;
5143
- }
5144
- }
5145
- if (modified) {
5146
- this.noteManager.writeNoteConfig(configPath, config2);
5147
- return true;
5148
- }
5149
- return false;
5150
- } catch (error) {
5151
- logger.error(`\u4FEE\u590D\u65F6\u95F4\u6233\u5931\u8D25: ${noteDir}`, error);
5152
- return false;
5153
- }
5154
- }
5155
- /**
5156
- * 修复根配置文件的时间戳
5157
- * @param forceUpdate - 是否强制更新
5158
- * @returns 是否进行了修复
5159
- */
5160
- fixRootConfigTimestamps(forceUpdate = false) {
5161
- try {
5162
- const configContent = readFileSync7(ROOT_CONFIG_PATH, "utf-8");
5163
- const config2 = JSON.parse(configContent);
5164
- const createdAtOutput = execSync3("git log --reverse --format=%ct", {
5165
- cwd: ROOT_DIR_PATH,
5166
- encoding: "utf-8",
5167
- stdio: ["pipe", "pipe", "ignore"]
5168
- }).trim();
5169
- const updatedAtOutput = execSync3("git log -1 --format=%ct", {
5170
- cwd: ROOT_DIR_PATH,
5171
- encoding: "utf-8",
5172
- stdio: ["pipe", "pipe", "ignore"]
5173
- }).trim();
5174
- if (!createdAtOutput || !updatedAtOutput) {
5175
- return false;
5176
- }
5177
- const firstTimestamp = createdAtOutput.split("\n")[0];
5178
- const createdAt = parseInt(firstTimestamp) * 1e3;
5179
- const updatedAt = parseInt(updatedAtOutput) * 1e3;
5180
- let modified = false;
5181
- if (forceUpdate || !config2.root_item.created_at || config2.root_item.created_at !== createdAt) {
5182
- config2.root_item.created_at = createdAt;
5183
- modified = true;
5184
- }
5185
- if (forceUpdate || !config2.root_item.updated_at || config2.root_item.updated_at !== updatedAt) {
5186
- config2.root_item.updated_at = updatedAt;
5187
- modified = true;
5188
- }
5189
- if (modified) {
5190
- const daysSinceBirth = Math.floor((updatedAt - BIRTH_DATE) / (1e3 * 60 * 60 * 24)) + 1;
5191
- config2.root_item.days_since_birth = daysSinceBirth;
5192
- writeFileSync6(
5193
- ROOT_CONFIG_PATH,
5194
- JSON.stringify(config2, null, 2) + "\n",
5195
- "utf-8"
5196
- );
5197
- return true;
5198
- }
5199
- return false;
5200
- } catch (error) {
5201
- logger.error("\u4FEE\u590D\u6839\u914D\u7F6E\u6587\u4EF6\u65F6\u95F4\u6233\u5931\u8D25", error);
5202
- return false;
5203
- }
5204
- }
5205
- /**
5206
- * 修复所有笔记的时间戳
5207
- * @param forceUpdate - 是否强制更新(忽略现有值,用于修复历史错误数据)
5208
- * @returns 修复统计信息
5209
- */
5210
- async fixAllTimestamps(forceUpdate = false) {
5211
- if (forceUpdate) {
5212
- logger.info("\u6B63\u5728\u5F3A\u5236\u4FEE\u590D\u7B14\u8BB0\u65F6\u95F4\u6233\uFF08\u4F7F\u7528 git \u771F\u5B9E\u65F6\u95F4\uFF09...");
5213
- } else {
5214
- logger.info("\u6B63\u5728\u4FEE\u590D\u7B14\u8BB0\u65F6\u95F4\u6233...");
5215
- }
5216
- const rootConfigFixed = this.fixRootConfigTimestamps(forceUpdate);
5217
- if (rootConfigFixed) {
5218
- logger.success("\u2705 \u6839\u914D\u7F6E\u6587\u4EF6\u65F6\u95F4\u6233\u5DF2\u4FEE\u590D");
5219
- }
5220
- const timestampMap = this.buildGitTimestampMap();
5221
- logger.info(`\u5DF2\u4ECE git \u5386\u53F2\u4E2D\u63D0\u53D6 ${timestampMap.size} \u4E2A\u6587\u4EF6\u7684\u65F6\u95F4\u6233\u4FE1\u606F`);
5222
- if (!existsSync8(NOTES_DIR_PATH)) {
5223
- logger.error("notes \u76EE\u5F55\u4E0D\u5B58\u5728");
5224
- return { fixed: 0, skipped: 0, total: 0, rootConfigFixed };
5225
- }
5226
- const noteDirs = readdirSync3(NOTES_DIR_PATH).filter((name) => {
5227
- const fullPath = join8(NOTES_DIR_PATH, name);
5228
- return statSync2(fullPath).isDirectory() && /^\d{4}\./.test(name);
5229
- }).sort();
5230
- let fixedCount = 0;
5231
- let skippedCount = 0;
5232
- for (const noteDir of noteDirs) {
5233
- const fixed = this.fixNoteTimestamps(noteDir, forceUpdate, timestampMap);
5234
- if (fixed) {
5235
- fixedCount++;
5236
- } else {
5237
- skippedCount++;
5238
- }
5239
- }
5240
- if (fixedCount > 0) {
5241
- logger.success(`\u65F6\u95F4\u6233\u4FEE\u590D\u5B8C\u6210: ${fixedCount} \u4E2A\u7B14\u8BB0\u5DF2\u66F4\u65B0`);
5242
- } else {
5243
- logger.info("\u6240\u6709\u7B14\u8BB0\u65F6\u95F4\u6233\u5747\u5DF2\u6B63\u786E");
5244
- }
5245
- return {
5246
- fixed: fixedCount,
5247
- skipped: skippedCount,
5248
- total: noteDirs.length,
5249
- rootConfigFixed
5250
- };
5251
- }
5252
- /**
5253
- * 更新指定笔记的时间戳为当前时间
5254
- * @param noteDirNames - 笔记目录名数组
5255
- * @returns 更新的笔记数量
5256
- */
5257
- async updateNotesTimestamp(noteDirNames) {
5258
- if (noteDirNames.length === 0) {
5259
- return 0;
5260
- }
5261
- const now = Date.now();
5262
- let updatedCount = 0;
5263
- for (const noteDir of noteDirNames) {
5264
- const configPath = join8(NOTES_DIR_PATH, noteDir, ".tnotes.json");
5265
- if (!existsSync8(configPath)) {
5266
- continue;
5267
- }
5268
- try {
5269
- const configContent = readFileSync7(configPath, "utf-8");
5270
- const config2 = JSON.parse(configContent);
5271
- config2.updated_at = now;
5272
- this.noteManager.writeNoteConfig(configPath, config2);
5273
- updatedCount++;
5274
- } catch (error) {
5275
- logger.error(`\u66F4\u65B0\u65F6\u95F4\u6233\u5931\u8D25: ${noteDir}`, error);
5276
- }
5277
- }
5278
- return updatedCount;
5279
- }
5280
- /**
5281
- * 获取本次变更中包含 README.md 的笔记列表
5282
- * @param changedFiles - git status 返回的变更文件列表
5283
- * @returns 变更的笔记目录名数组
5284
- */
5285
- getChangedNotes(changedFiles) {
5286
- const changedNotes = /* @__PURE__ */ new Set();
5287
- for (let file of changedFiles) {
5288
- file = file.replace(/^"(.*)"$/, "$1").replace(/"$/, "");
5289
- const match = file.match(/^notes\/([^/]+)\/README\.md$/);
5290
- if (match) {
5291
- changedNotes.add(match[1]);
5292
- }
5293
- }
5294
- return Array.from(changedNotes);
5295
- }
5296
- };
5297
-
5298
4980
  // services/vitepress/service.ts
5299
4981
  import { spawn as spawn2 } from "child_process";
5300
4982
  var VitepressService = class _VitepressService {
@@ -5524,13 +5206,13 @@ var VitepressService = class _VitepressService {
5524
5206
  };
5525
5207
 
5526
5208
  // services/init-sub-repo/service.ts
5527
- import { copyFileSync, existsSync as existsSync10, mkdirSync, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
5528
- import { dirname as dirname2, join as join10, resolve as resolve3 } from "path";
5209
+ import { copyFileSync, existsSync as existsSync9, mkdirSync, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
5210
+ import { dirname as dirname2, join as join9, resolve as resolve3 } from "path";
5529
5211
  import { fileURLToPath } from "url";
5530
5212
 
5531
5213
  // services/init-sub-repo/initSubRepoLogic.ts
5532
- import { existsSync as existsSync9, readFileSync as readFileSync8 } from "fs";
5533
- import { join as join9, resolve as resolve2 } from "path";
5214
+ import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
5215
+ import { join as join8, resolve as resolve2 } from "path";
5534
5216
  var TOPIC_PATTERN = /^[a-z][a-z0-9-]*$/;
5535
5217
  var DEFAULT_PORT = 8e3;
5536
5218
  var DEFAULT_DESCRIPTION = "\u8FD9\u662F\u4E00\u4E2A\u57FA\u4E8E tnotesjs/core \u642D\u5EFA\u7684 TNotes \u77E5\u8BC6\u5E93\u3002";
@@ -5659,7 +5341,6 @@ function buildPackageJsonTemplate(coreVersion) {
5659
5341
  "tn:build": "tnotes --build",
5660
5342
  "tn:create-notes": "tnotes --create-notes",
5661
5343
  "tn:dev": "tnotes --dev",
5662
- "tn:fix-timestamps": "tnotes --fix-timestamps",
5663
5344
  "tn:help": "tnotes --help",
5664
5345
  "tn:init-sub-repo": "tnotes --init-sub-repo",
5665
5346
  "tn:preview": "tnotes --preview",
@@ -5712,31 +5393,31 @@ function buildDynamicFiles(ctx) {
5712
5393
  content: renderRootReadme(ctx)
5713
5394
  },
5714
5395
  {
5715
- relativePath: join9("notes", ctx.noteDirName, "README.md"),
5396
+ relativePath: join8("notes", ctx.noteDirName, "README.md"),
5716
5397
  content: renderFirstNoteReadme(ctx)
5717
5398
  },
5718
5399
  {
5719
- relativePath: join9("notes", ctx.noteDirName, ".tnotes.json"),
5400
+ relativePath: join8("notes", ctx.noteDirName, ".tnotes.json"),
5720
5401
  content: `${JSON.stringify(buildNoteConfig(ctx.noteUuid), null, 2)}
5721
5402
  `
5722
5403
  }
5723
5404
  ];
5724
5405
  }
5725
5406
  function isAlreadyInitialized(rootPath2) {
5726
- return existsSync9(resolve2(rootPath2, ".tnotes.json"));
5407
+ return existsSync8(resolve2(rootPath2, ".tnotes.json"));
5727
5408
  }
5728
5409
  function getInitializedConfigPath(rootPath2) {
5729
5410
  return resolve2(rootPath2, ".tnotes.json");
5730
5411
  }
5731
5412
  function resolvePackageJsonMerge(targetPath, template) {
5732
- if (!existsSync9(targetPath)) {
5413
+ if (!existsSync8(targetPath)) {
5733
5414
  return {
5734
5415
  content: `${JSON.stringify(template, null, 2)}
5735
5416
  `,
5736
5417
  action: "created"
5737
5418
  };
5738
5419
  }
5739
- const existing = JSON.parse(readFileSync8(targetPath, "utf-8"));
5420
+ const existing = JSON.parse(readFileSync7(targetPath, "utf-8"));
5740
5421
  const merged = mergePackageJson(existing, template);
5741
5422
  return {
5742
5423
  content: `${JSON.stringify(merged, null, 2)}
@@ -5761,9 +5442,9 @@ function buildManualSteps(ctx) {
5761
5442
  function getCorePackageRoot(fromModuleUrl) {
5762
5443
  let dir = dirname2(fileURLToPath(fromModuleUrl));
5763
5444
  while (dir !== dirname2(dir)) {
5764
- const pkgPath = join10(dir, "package.json");
5765
- if (existsSync10(pkgPath)) {
5766
- const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
5445
+ const pkgPath = join9(dir, "package.json");
5446
+ if (existsSync9(pkgPath)) {
5447
+ const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
5767
5448
  if (pkg.name === "@tnotesjs/core") return dir;
5768
5449
  }
5769
5450
  dir = dirname2(dir);
@@ -5771,7 +5452,7 @@ function getCorePackageRoot(fromModuleUrl) {
5771
5452
  throw new Error("\u65E0\u6CD5\u5B9A\u4F4D @tnotesjs/core \u5305\u6839\u76EE\u5F55");
5772
5453
  }
5773
5454
  function getTemplateRoot(fromModuleUrl) {
5774
- return join10(getCorePackageRoot(fromModuleUrl), "templates", "sub-repo");
5455
+ return join9(getCorePackageRoot(fromModuleUrl), "templates", "sub-repo");
5775
5456
  }
5776
5457
  var InitSubRepoService = class _InitSubRepoService {
5777
5458
  constructor(rootPath2, templateRoot) {
@@ -5788,11 +5469,11 @@ var InitSubRepoService = class _InitSubRepoService {
5788
5469
  const updated = [];
5789
5470
  for (const relativePath of STATIC_TEMPLATE_FILES) {
5790
5471
  const targetPath = resolve3(this.rootPath, relativePath);
5791
- if (existsSync10(targetPath)) {
5472
+ if (existsSync9(targetPath)) {
5792
5473
  skipped.push(relativePath);
5793
5474
  continue;
5794
5475
  }
5795
- const sourcePath = join10(this.templateRoot, relativePath);
5476
+ const sourcePath = join9(this.templateRoot, relativePath);
5796
5477
  mkdirSync(dirname2(targetPath), { recursive: true });
5797
5478
  copyFileSync(sourcePath, targetPath);
5798
5479
  created.push(relativePath);
@@ -5806,17 +5487,17 @@ var InitSubRepoService = class _InitSubRepoService {
5806
5487
  packageTemplate
5807
5488
  );
5808
5489
  mkdirSync(dirname2(targetPath), { recursive: true });
5809
- writeFileSync7(targetPath, content, "utf-8");
5490
+ writeFileSync6(targetPath, content, "utf-8");
5810
5491
  if (action === "created") created.push(file.relativePath);
5811
5492
  else updated.push(file.relativePath);
5812
5493
  continue;
5813
5494
  }
5814
- if (existsSync10(targetPath)) {
5495
+ if (existsSync9(targetPath)) {
5815
5496
  skipped.push(file.relativePath);
5816
5497
  continue;
5817
5498
  }
5818
5499
  mkdirSync(dirname2(targetPath), { recursive: true });
5819
- writeFileSync7(targetPath, file.content, "utf-8");
5500
+ writeFileSync6(targetPath, file.content, "utf-8");
5820
5501
  created.push(file.relativePath);
5821
5502
  }
5822
5503
  return { created, skipped, updated };
@@ -5907,8 +5588,8 @@ var UpdateNoteConfigCommand = class extends BaseCommand {
5907
5588
  };
5908
5589
 
5909
5590
  // commands/note/RenameNoteCommand.ts
5910
- import { existsSync as existsSync11, renameSync, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
5911
- import { join as join11 } from "path";
5591
+ import { existsSync as existsSync10, renameSync, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
5592
+ import { join as join10 } from "path";
5912
5593
  var RenameNoteCommand = class extends BaseCommand {
5913
5594
  constructor() {
5914
5595
  super("rename-note");
@@ -5943,8 +5624,8 @@ var RenameNoteCommand = class extends BaseCommand {
5943
5624
  throw new Error(validation.error || "\u6807\u9898\u683C\u5F0F\u65E0\u6548");
5944
5625
  }
5945
5626
  const newDirName = `${noteIndex}. ${newTitle.trim()}`;
5946
- const newPath = join11(NOTES_PATH, newDirName);
5947
- if (existsSync11(newPath)) {
5627
+ const newPath = join10(NOTES_PATH, newDirName);
5628
+ if (existsSync10(newPath)) {
5948
5629
  throw new Error(`\u76EE\u6807\u6587\u4EF6\u5939\u5DF2\u5B58\u5728: ${newDirName}`);
5949
5630
  }
5950
5631
  const watcher = FileWatcherService.getInstance();
@@ -5963,9 +5644,9 @@ var RenameNoteCommand = class extends BaseCommand {
5963
5644
  }
5964
5645
  try {
5965
5646
  this.logger.info("\u6B63\u5728\u66F4\u65B0\u7B14\u8BB0\u5185\u90E8\u6807\u9898...");
5966
- const readmePath = join11(newPath, "README.md");
5967
- if (existsSync11(readmePath)) {
5968
- const content = readFileSync10(readmePath, "utf-8");
5647
+ const readmePath = join10(newPath, "README.md");
5648
+ if (existsSync10(readmePath)) {
5649
+ const content = readFileSync9(readmePath, "utf-8");
5969
5650
  const lines = content.split("\n");
5970
5651
  let h1Index = -1;
5971
5652
  for (let i = 0; i < lines.length; i++) {
@@ -5981,7 +5662,7 @@ var RenameNoteCommand = class extends BaseCommand {
5981
5662
  REPO_NOTES_URL
5982
5663
  );
5983
5664
  lines[h1Index] = newH1;
5984
- writeFileSync8(readmePath, lines.join("\n"), "utf-8");
5665
+ writeFileSync7(readmePath, lines.join("\n"), "utf-8");
5985
5666
  this.logger.success("\u2705 \u7B14\u8BB0\u6807\u9898\u5DF2\u66F4\u65B0");
5986
5667
  } else {
5987
5668
  this.logger.warn(
@@ -6029,7 +5710,6 @@ export {
6029
5710
  FileWatcherService,
6030
5711
  GitManager,
6031
5712
  GitService,
6032
- TimestampService,
6033
5713
  VitepressService,
6034
5714
  DEFAULT_PORT,
6035
5715
  DEFAULT_DESCRIPTION,