@tnotesjs/core 0.2.2 → 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 (35) hide show
  1. package/README.md +0 -1
  2. package/config/defaultConfig.ts +33 -4
  3. package/config/index.ts +6 -0
  4. package/core/NoteIndexCache.ts +7 -1
  5. package/core/NoteManager.ts +18 -30
  6. package/dist/{chunk-5Y5IYS6C.js → chunk-UJG3UU5X.js} +21 -5
  7. package/dist/{chunk-5QN44ES5.js → chunk-XCWFZLER.js} +48 -368
  8. package/dist/cli/index.js +26 -78
  9. package/dist/index.js +1 -1
  10. package/dist/vitepress/config/index.js +2 -2
  11. package/package.json +1 -1
  12. package/services/index.ts +0 -1
  13. package/services/init-sub-repo/initSubRepoLogic.ts +0 -1
  14. package/services/note/service.ts +0 -1
  15. package/types/config.ts +0 -3
  16. package/types/note.ts +0 -2
  17. package/vitepress/assets/icons/icon__cursor.svg +4 -0
  18. package/vitepress/assets/icons/index.ts +1 -0
  19. package/vitepress/components/Layout/AboutPanel.vue +0 -24
  20. package/vitepress/components/Layout/DocBeforeControls.vue +6 -14
  21. package/vitepress/components/Layout/DocFooter.vue +3 -3
  22. package/vitepress/components/Layout/Layout.vue +0 -30
  23. package/vitepress/components/Layout/composables/useVSCodeIntegration.ts +20 -11
  24. package/vitepress/components/Layout/homeReadme.data.ts +0 -48
  25. package/vitepress/components/MarkMap/MarkMap.vue +6 -13
  26. package/vitepress/components/Settings/Settings.vue +76 -73
  27. package/vitepress/components/SidebarCard/FolderTreeItems.vue +16 -6
  28. package/vitepress/components/SidebarCard/SidebarCard.vue +21 -27
  29. package/vitepress/components/composables/useLocalIde.ts +83 -0
  30. package/vitepress/components/constants.ts +5 -6
  31. package/vitepress/components/utils/vscodePaths.test.ts +22 -0
  32. package/vitepress/components/utils/vscodePaths.ts +24 -2
  33. package/vitepress/theme/styles/doc-layout.scss +4 -4
  34. package/services/timestamp/index.ts +0 -7
  35. package/services/timestamp/service.ts +0 -465
package/README.md CHANGED
@@ -69,7 +69,6 @@ export { default } from '@tnotesjs/core/vitepress/theme'
69
69
  "tn:push": "tnotes --push",
70
70
  "tn:pull": "tnotes --pull",
71
71
  "tn:create-notes": "tnotes --create-notes",
72
- "tn:fix-timestamps": "tnotes --fix-timestamps",
73
72
  "tn:help": "tnotes --help",
74
73
  "tn:init-sub-repo": "tnotes --init-sub-repo"
75
74
  }
@@ -44,9 +44,6 @@ export function getDefaultConfig(repoName?: string): TNotesConfig {
44
44
  completed_notes_count: {},
45
45
  details: `${name} 知识库`,
46
46
  link: `https://tnotesjs.github.io/${name}/`,
47
- created_at: Date.now(),
48
- updated_at: Date.now(),
49
- days_since_birth: 0,
50
47
  },
51
48
 
52
49
  // 端口配置(根据仓库名生成)
@@ -120,6 +117,32 @@ export function mergeConfig(
120
117
  return result
121
118
  }
122
119
 
120
+ /**
121
+ * 根配置 root_item 中已废弃的字段
122
+ */
123
+ const DEPRECATED_ROOT_ITEM_FIELDS = [
124
+ 'created_at',
125
+ 'updated_at',
126
+ 'days_since_birth',
127
+ ] as const
128
+
129
+ /**
130
+ * 剥离 root_item 中的废弃时间戳字段
131
+ * @returns 是否删除了字段
132
+ */
133
+ export function stripDeprecatedRootItemFields(
134
+ rootItem: Record<string, unknown>,
135
+ ): boolean {
136
+ let stripped = false
137
+ for (const key of DEPRECATED_ROOT_ITEM_FIELDS) {
138
+ if (key in rootItem) {
139
+ delete rootItem[key]
140
+ stripped = true
141
+ }
142
+ }
143
+ return stripped
144
+ }
145
+
123
146
  /**
124
147
  * 验证并补全配置
125
148
  * @param config - 现有配置
@@ -135,8 +158,14 @@ export function validateAndCompleteConfig(config: Record<string, any>): {
135
158
  // 深度合并配置
136
159
  const mergedConfig = mergeConfig(config, defaultConfig as any)
137
160
 
161
+ // 剥离 root_item 废弃字段
162
+ const rootItem = (mergedConfig.root_item || {}) as Record<string, unknown>
163
+ const stripped = stripDeprecatedRootItemFields(rootItem)
164
+ mergedConfig.root_item = rootItem
165
+
138
166
  // 检查是否有修改
139
- const modified = JSON.stringify(config) !== JSON.stringify(mergedConfig)
167
+ const modified =
168
+ stripped || JSON.stringify(config) !== JSON.stringify(mergedConfig)
140
169
 
141
170
  return {
142
171
  config: mergedConfig as TNotesConfig,
package/config/index.ts CHANGED
@@ -8,6 +8,12 @@ export {
8
8
  ConfigManager,
9
9
  getConfigManager,
10
10
  } from './ConfigManager'
11
+ export {
12
+ getDefaultConfig,
13
+ mergeConfig,
14
+ validateAndCompleteConfig,
15
+ stripDeprecatedRootItemFields,
16
+ } from './defaultConfig'
11
17
  export {
12
18
  ROOT_DIR_PATH,
13
19
  ROOT_README_PATH,
@@ -136,7 +136,13 @@ export class NoteIndexCache {
136
136
  }
137
137
 
138
138
  Object.assign(item.noteConfig, configUpdates)
139
- item.noteConfig.updated_at = Date.now()
139
+ // 剥离内存中残留的废弃时间戳字段,避免后续写回时恢复
140
+ const noteConfigRecord = item.noteConfig as unknown as Record<
141
+ string,
142
+ unknown
143
+ >
144
+ delete noteConfigRecord.created_at
145
+ delete noteConfigRecord.updated_at
140
146
 
141
147
  logger.debug(`更新笔记配置: ${noteIndex}`, configUpdates)
142
148
  }
@@ -210,8 +210,6 @@ export class NoteManager {
210
210
  'enableDiscussions',
211
211
  'description',
212
212
  'id',
213
- 'created_at',
214
- 'updated_at',
215
213
  ]
216
214
 
217
215
  /** 默认配置字段 */
@@ -224,6 +222,12 @@ export class NoteManager {
224
222
  description: '',
225
223
  } as const
226
224
 
225
+ /** 已废弃、写回时需剥离的笔记配置字段 */
226
+ private static readonly DEPRECATED_CONFIG_FIELDS = [
227
+ 'created_at',
228
+ 'updated_at',
229
+ ] as const
230
+
227
231
  /** 必需字段(不能缺失) */
228
232
  private static readonly REQUIRED_FIELDS = ['id'] as const
229
233
 
@@ -244,6 +248,7 @@ export class NoteManager {
244
248
  }
245
249
 
246
250
  let needsUpdate = false
251
+ const configRecord = config as Record<string, unknown>
247
252
 
248
253
  // 1. 检查必需字段 —— 缺失时直接返回 null,由 validateNotes() 统一报告
249
254
  for (const field of NoteManager.REQUIRED_FIELDS) {
@@ -257,32 +262,22 @@ export class NoteManager {
257
262
  NoteManager.DEFAULT_CONFIG_FIELDS,
258
263
  )) {
259
264
  if (!(key in config)) {
260
- ;(config as Record<string, unknown>)[key] = defaultValue
265
+ configRecord[key] = defaultValue
261
266
  needsUpdate = true
262
267
  logger.info(`补充缺失字段 "${key}": ${configPath}`)
263
268
  }
264
269
  }
265
270
 
266
- // 3. 确保时间戳字段存在
267
- // 这里仅用 Date.now() 占位,确保字段不缺失。
268
- // 真实的 git 时间戳由 tn:fix-timestamps 命令统一校准。
269
- const now = Date.now()
270
- if (!config.created_at) {
271
- config.created_at = now
272
- needsUpdate = true
273
- logger.info(
274
- `检测到 ${configPath} 缺失 created_at 字段,请执行 tn:fix-timestamps 校准为笔记首次 git commit 的时间)`,
275
- )
276
- }
277
- if (!config.updated_at) {
278
- config.updated_at = now
279
- needsUpdate = true
280
- logger.info(
281
- `检测到 ${configPath} 缺失 updated_at 字段,请执行 tn:fix-timestamps 校准为笔记最后一次 git commit 的时间)`,
282
- )
271
+ // 3. 剥离已废弃字段(created_at / updated_at)
272
+ for (const key of NoteManager.DEPRECATED_CONFIG_FIELDS) {
273
+ if (key in configRecord) {
274
+ delete configRecord[key]
275
+ needsUpdate = true
276
+ logger.info(`移除废弃字段 "${key}": ${configPath}`)
277
+ }
283
278
  }
284
279
 
285
- // 4. 按字段顺序排序
280
+ // 4. 按字段顺序排序(仅保留白名单字段)
286
281
  const sortedConfig = this.sortConfigKeys(config as NoteConfig)
287
282
 
288
283
  // 5. 写回文件(如果有变更)
@@ -295,20 +290,14 @@ export class NoteManager {
295
290
  }
296
291
 
297
292
  /**
298
- * 按指定顺序排序配置对象的键
293
+ * 按指定顺序排序配置对象的键(仅保留已知字段,丢弃废弃/未知字段)
299
294
  */
300
295
  private sortConfigKeys(config: NoteConfig): NoteConfig {
301
296
  const configRecord = config as unknown as Record<string, unknown>
302
297
  const sorted: Record<string, unknown> = {}
303
298
 
304
299
  for (const key of NoteManager.FIELD_ORDER) {
305
- if (key in config) {
306
- sorted[key] = configRecord[key]
307
- }
308
- }
309
-
310
- for (const key of Object.keys(config)) {
311
- if (!(key in sorted)) {
300
+ if (key in configRecord) {
312
301
  sorted[key] = configRecord[key]
313
302
  }
314
303
  }
@@ -383,7 +372,6 @@ export class NoteManager {
383
372
  throw new Error(`Invalid config for note: ${noteInfo.dirName}`)
384
373
  }
385
374
 
386
- config.updated_at = Date.now()
387
375
  this.writeNoteConfig(noteInfo.configPath, config)
388
376
  logger.info(`Updated config for note: ${noteInfo.dirName}`)
389
377
  }
@@ -32,10 +32,7 @@ function getDefaultConfig(repoName) {
32
32
  title: cleanName,
33
33
  completed_notes_count: {},
34
34
  details: `${name} \u77E5\u8BC6\u5E93`,
35
- link: `https://tnotesjs.github.io/${name}/`,
36
- created_at: Date.now(),
37
- updated_at: Date.now(),
38
- days_since_birth: 0
35
+ link: `https://tnotesjs.github.io/${name}/`
39
36
  },
40
37
  // 端口配置(根据仓库名生成)
41
38
  port: 8e3,
@@ -86,11 +83,29 @@ function mergeConfig(target, source) {
86
83
  }
87
84
  return result;
88
85
  }
86
+ var DEPRECATED_ROOT_ITEM_FIELDS = [
87
+ "created_at",
88
+ "updated_at",
89
+ "days_since_birth"
90
+ ];
91
+ function stripDeprecatedRootItemFields(rootItem) {
92
+ let stripped = false;
93
+ for (const key of DEPRECATED_ROOT_ITEM_FIELDS) {
94
+ if (key in rootItem) {
95
+ delete rootItem[key];
96
+ stripped = true;
97
+ }
98
+ }
99
+ return stripped;
100
+ }
89
101
  function validateAndCompleteConfig(config) {
90
102
  const repoName = config.repoName || "TNotes.default";
91
103
  const defaultConfig = getDefaultConfig(repoName);
92
104
  const mergedConfig = mergeConfig(config, defaultConfig);
93
- const modified = JSON.stringify(config) !== JSON.stringify(mergedConfig);
105
+ const rootItem = mergedConfig.root_item || {};
106
+ const stripped = stripDeprecatedRootItemFields(rootItem);
107
+ mergedConfig.root_item = rootItem;
108
+ const modified = stripped || JSON.stringify(config) !== JSON.stringify(mergedConfig);
94
109
  return {
95
110
  config: mergedConfig,
96
111
  modified
@@ -195,6 +210,7 @@ function getConfigManager() {
195
210
 
196
211
  export {
197
212
  getDefaultConfig,
213
+ stripDeprecatedRootItemFields,
198
214
  ConfigManager,
199
215
  getConfigManager
200
216
  };