@tnotesjs/core 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/ConfigManager.ts +137 -0
- package/config/constants.ts +121 -0
- package/config/index.ts +25 -0
- package/config/templates.ts +49 -0
- package/core/GitManager.ts +513 -0
- package/core/NoteIndexCache.ts +194 -0
- package/core/NoteManager.ts +407 -0
- package/core/ProcessManager.ts +180 -0
- package/core/ReadmeGenerator.ts +215 -0
- package/core/TocGenerator.ts +212 -0
- package/core/index.ts +11 -0
- package/dist/chunk-5QN44ES5.js +6050 -0
- package/dist/chunk-5Y5IYS6C.js +200 -0
- package/dist/cli/index.js +986 -0
- package/dist/index.js +8 -0
- package/dist/vitepress/config/index.js +1686 -0
- package/package.json +6 -2
- package/services/file-watcher/configChangeHandler.ts +64 -0
- package/services/file-watcher/eventScheduler.ts +179 -0
- package/services/file-watcher/folderChangeHandler.ts +325 -0
- package/services/file-watcher/fsWatcherAdapter.ts +128 -0
- package/services/file-watcher/globalUpdateCoordinator.ts +60 -0
- package/services/file-watcher/index.ts +7 -0
- package/services/file-watcher/internal.ts +79 -0
- package/services/file-watcher/readmeChangeHandler.ts +28 -0
- package/services/file-watcher/renameDetector.ts +120 -0
- package/services/file-watcher/service.ts +352 -0
- package/services/file-watcher/watchState.ts +194 -0
- package/services/git/index.ts +7 -0
- package/services/git/service.ts +114 -0
- package/services/index.ts +15 -0
- package/services/init-sub-repo/index.ts +2 -0
- package/services/init-sub-repo/initSubRepoLogic.test.ts +162 -0
- package/services/init-sub-repo/initSubRepoLogic.ts +304 -0
- package/services/init-sub-repo/service.ts +101 -0
- package/services/note/index.ts +7 -0
- package/services/note/service.ts +362 -0
- package/services/readme/index.ts +7 -0
- package/services/readme/service.ts +761 -0
- package/services/timestamp/index.ts +7 -0
- package/services/timestamp/service.ts +465 -0
- package/services/toc/index.ts +5 -0
- package/services/toc/moveTocInside.test.ts +73 -0
- package/services/toc/service.ts +759 -0
- package/services/vitepress/index.ts +7 -0
- package/services/vitepress/service.ts +339 -0
- package/utils/errorHandler.ts +174 -0
- package/utils/file.ts +17 -0
- package/utils/genHierarchicalSidebar.ts +69 -0
- package/utils/generateAnchor.ts +24 -0
- package/utils/getChangedIds.ts +35 -0
- package/utils/index.ts +71 -0
- package/utils/logger.ts +231 -0
- package/utils/markdown.ts +75 -0
- package/utils/migrateReadmeToToc.test.ts +111 -0
- package/utils/migrateReadmeToToc.ts +135 -0
- package/utils/parseArgs.ts +90 -0
- package/utils/parseReadmeCompletedNotes.test.ts +90 -0
- package/utils/parseReadmeCompletedNotes.ts +108 -0
- package/utils/portUtils.ts +113 -0
- package/utils/readmeHelpers.ts +190 -0
- package/utils/runCommand.ts +29 -0
- package/utils/tocHelpers.test.ts +278 -0
- package/utils/tocHelpers.ts +855 -0
- package/utils/tocNodeId.test.ts +60 -0
- package/utils/tocNodeId.ts +97 -0
- package/utils/validators.ts +102 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config/ConfigManager.ts
|
|
3
|
+
*
|
|
4
|
+
* 配置管理器 - 统一管理项目配置
|
|
5
|
+
*/
|
|
6
|
+
import fs from 'fs'
|
|
7
|
+
import path from 'path'
|
|
8
|
+
|
|
9
|
+
import { validateAndCompleteConfig } from './defaultConfig'
|
|
10
|
+
|
|
11
|
+
import type { TNotesConfig } from '../types'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 配置管理器(单例模式)
|
|
15
|
+
*/
|
|
16
|
+
export class ConfigManager {
|
|
17
|
+
private static instance: ConfigManager
|
|
18
|
+
private config: TNotesConfig | null = null
|
|
19
|
+
private configPath: string
|
|
20
|
+
private rootPath: string
|
|
21
|
+
|
|
22
|
+
private constructor(rootPath?: string) {
|
|
23
|
+
if (rootPath) {
|
|
24
|
+
// 显式传入根路径
|
|
25
|
+
this.rootPath = rootPath
|
|
26
|
+
} else {
|
|
27
|
+
// 默认使用 process.cwd()(CLI 和 VitePress 均在项目根目录执行)
|
|
28
|
+
this.rootPath = process.cwd()
|
|
29
|
+
}
|
|
30
|
+
this.configPath = path.normalize(
|
|
31
|
+
path.resolve(this.rootPath, '.tnotes.json'),
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* 使用指定的根路径初始化配置管理器
|
|
37
|
+
*
|
|
38
|
+
* 必须在 getInstance() 之前调用(如果需要指定 rootPath)。
|
|
39
|
+
* 如果已经初始化,则忽略重复调用。
|
|
40
|
+
*/
|
|
41
|
+
static init({ rootPath }: { rootPath: string }): ConfigManager {
|
|
42
|
+
if (!ConfigManager.instance) {
|
|
43
|
+
ConfigManager.instance = new ConfigManager(rootPath)
|
|
44
|
+
}
|
|
45
|
+
return ConfigManager.instance
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 获取单例实例
|
|
50
|
+
*/
|
|
51
|
+
static getInstance(): ConfigManager {
|
|
52
|
+
if (!ConfigManager.instance) {
|
|
53
|
+
ConfigManager.instance = new ConfigManager()
|
|
54
|
+
}
|
|
55
|
+
return ConfigManager.instance
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 加载配置文件
|
|
60
|
+
*/
|
|
61
|
+
loadConfig(configPath?: string): TNotesConfig {
|
|
62
|
+
if (this.config) return this.config
|
|
63
|
+
|
|
64
|
+
const path = configPath || this.configPath
|
|
65
|
+
|
|
66
|
+
if (!fs.existsSync(path)) {
|
|
67
|
+
throw new Error(`配置文件不存在: ${path}`)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const configContent = fs.readFileSync(path, 'utf-8')
|
|
71
|
+
const rawConfig = JSON.parse(configContent)
|
|
72
|
+
|
|
73
|
+
// 验证并补全配置
|
|
74
|
+
const { config: validatedConfig, modified } =
|
|
75
|
+
validateAndCompleteConfig(rawConfig)
|
|
76
|
+
|
|
77
|
+
if (modified) {
|
|
78
|
+
console.warn(`[ConfigManager] 检测到知识库配置缺失字段,已自动补全`)
|
|
79
|
+
// 写回配置文件
|
|
80
|
+
fs.writeFileSync(path, JSON.stringify(validatedConfig, null, 2), 'utf-8')
|
|
81
|
+
console.log(`[ConfigManager] 知识库配置文件已更新`)
|
|
82
|
+
console.log(`[ConfigManager] 知识库配置文件路径: ${path}`)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
this.config = validatedConfig
|
|
86
|
+
|
|
87
|
+
return this.config
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 清除内存中的配置缓存,下次 get/getAll 时重新从磁盘加载
|
|
92
|
+
*/
|
|
93
|
+
clearCache(): void {
|
|
94
|
+
this.config = null
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 获取配置项
|
|
99
|
+
*/
|
|
100
|
+
get<K extends keyof TNotesConfig>(key: K): TNotesConfig[K] {
|
|
101
|
+
if (!this.config) {
|
|
102
|
+
this.loadConfig()
|
|
103
|
+
}
|
|
104
|
+
return this.config![key]
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 获取所有配置
|
|
109
|
+
*/
|
|
110
|
+
getAll(): TNotesConfig {
|
|
111
|
+
if (!this.config) {
|
|
112
|
+
this.loadConfig()
|
|
113
|
+
}
|
|
114
|
+
return this.config!
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* 获取项目根路径
|
|
119
|
+
*/
|
|
120
|
+
getRootPath(): string {
|
|
121
|
+
return this.rootPath
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @deprecated 使用 getRootPath() 替代
|
|
126
|
+
*/
|
|
127
|
+
getDirname(): string {
|
|
128
|
+
return path.resolve(this.rootPath, '.vitepress', 'tnotes', 'config')
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 获取配置管理器实例(便捷函数)
|
|
134
|
+
*/
|
|
135
|
+
export function getConfigManager(): ConfigManager {
|
|
136
|
+
return ConfigManager.getInstance()
|
|
137
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config/constants.ts
|
|
3
|
+
*
|
|
4
|
+
* 常量定义(从配置中派生的路径和URL常量)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { resolve } from 'path'
|
|
8
|
+
|
|
9
|
+
import { getConfigManager } from './ConfigManager'
|
|
10
|
+
import { getDefaultConfig } from './defaultConfig'
|
|
11
|
+
|
|
12
|
+
import type { TNotesConfig } from '../types'
|
|
13
|
+
|
|
14
|
+
function loadConfigOrDefault(): TNotesConfig {
|
|
15
|
+
try {
|
|
16
|
+
return getConfigManager().getAll()
|
|
17
|
+
} catch {
|
|
18
|
+
return getDefaultConfig()
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const configManager = getConfigManager()
|
|
23
|
+
const config = loadConfigOrDefault()
|
|
24
|
+
|
|
25
|
+
// 导出配置项(向后兼容)
|
|
26
|
+
export const {
|
|
27
|
+
author,
|
|
28
|
+
ignore_dirs,
|
|
29
|
+
menuItems,
|
|
30
|
+
port,
|
|
31
|
+
repoName,
|
|
32
|
+
sidebarShowNoteId,
|
|
33
|
+
socialLinks,
|
|
34
|
+
root_item,
|
|
35
|
+
} = config
|
|
36
|
+
|
|
37
|
+
// 目录常量 —— 从 ConfigManager.getRootPath() 派生
|
|
38
|
+
const rootPath = configManager.getRootPath()
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* TNotes.* 当前的笔记仓库根路径
|
|
42
|
+
* @example `/Users/huyouda/zm/notes/TNotes.template/`
|
|
43
|
+
*/
|
|
44
|
+
export const ROOT_DIR_PATH = rootPath
|
|
45
|
+
export const ROOT_README_PATH = resolve(ROOT_DIR_PATH, 'README.md')
|
|
46
|
+
export const ROOT_TOC_PATH = resolve(ROOT_DIR_PATH, 'TOC.md')
|
|
47
|
+
export const ROOT_CONFIG_PATH = resolve(ROOT_DIR_PATH, '.tnotes.json')
|
|
48
|
+
export const NOTES_DIR_PATH = resolve(ROOT_DIR_PATH, 'notes')
|
|
49
|
+
export const VP_DIR_PATH = resolve(ROOT_DIR_PATH, '.vitepress')
|
|
50
|
+
export const PUBLIC_PATH = resolve(ROOT_DIR_PATH, 'public')
|
|
51
|
+
export const GITHUB_DIR_PATH = resolve(ROOT_DIR_PATH, '.github')
|
|
52
|
+
export const GITHUB_DEPLOY_YML_PATH = resolve(
|
|
53
|
+
GITHUB_DIR_PATH,
|
|
54
|
+
'workflows',
|
|
55
|
+
'deploy.yml',
|
|
56
|
+
)
|
|
57
|
+
export const VP_SIDEBAR_PATH = resolve(ROOT_DIR_PATH, 'sidebar.json')
|
|
58
|
+
export const ROOT_PKG_PATH = resolve(ROOT_DIR_PATH, 'package.json')
|
|
59
|
+
export const VSCODE_SETTINGS_PATH = resolve(
|
|
60
|
+
ROOT_DIR_PATH,
|
|
61
|
+
'.vscode',
|
|
62
|
+
'settings.json',
|
|
63
|
+
)
|
|
64
|
+
export const VSCODE_TASKS_PATH = resolve(ROOT_DIR_PATH, '.vscode', 'tasks.json')
|
|
65
|
+
|
|
66
|
+
// 文本常量
|
|
67
|
+
export const EOL = '\n'
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* TNotes 常量配置
|
|
71
|
+
*/
|
|
72
|
+
export const CONSTANTS = {
|
|
73
|
+
// 端口配置
|
|
74
|
+
DEFAULT_PORT: 5173,
|
|
75
|
+
|
|
76
|
+
// 笔记索引配置(文件夹前缀的 4 位数字)
|
|
77
|
+
NOTE_INDEX_LENGTH: 4,
|
|
78
|
+
NOTE_INDEX_PATTERN: /^\d{4}\./,
|
|
79
|
+
NOTE_INDEX_PREFIX_PATTERN: /^\d{4}/,
|
|
80
|
+
|
|
81
|
+
// Git 配置
|
|
82
|
+
DEFAULT_BRANCH: 'main',
|
|
83
|
+
|
|
84
|
+
// 缓存配置
|
|
85
|
+
CACHE_TTL: 5000,
|
|
86
|
+
|
|
87
|
+
// 终端输出颜色
|
|
88
|
+
COLORS: {
|
|
89
|
+
RESET: '\x1b[0m',
|
|
90
|
+
BRIGHT: '\x1b[1m',
|
|
91
|
+
DIM: '\x1b[2m',
|
|
92
|
+
RED: '\x1b[31m',
|
|
93
|
+
GREEN: '\x1b[32m',
|
|
94
|
+
YELLOW: '\x1b[33m',
|
|
95
|
+
BLUE: '\x1b[34m',
|
|
96
|
+
MAGENTA: '\x1b[35m',
|
|
97
|
+
CYAN: '\x1b[36m',
|
|
98
|
+
} as const,
|
|
99
|
+
|
|
100
|
+
// Emoji
|
|
101
|
+
EMOJI: {
|
|
102
|
+
SUCCESS: '✅',
|
|
103
|
+
ERROR: '❌',
|
|
104
|
+
WARNING: '⚠️',
|
|
105
|
+
INFO: 'ℹ️',
|
|
106
|
+
PROGRESS: '⏳',
|
|
107
|
+
ROCKET: '🚀',
|
|
108
|
+
STOP: '🛑',
|
|
109
|
+
SPARKLES: '✨',
|
|
110
|
+
LINK: '🔗',
|
|
111
|
+
FILE: '📄',
|
|
112
|
+
GIT: '📦',
|
|
113
|
+
DEBUG: '🐛',
|
|
114
|
+
} as const,
|
|
115
|
+
} as const
|
|
116
|
+
|
|
117
|
+
// 导出路径常量别名(向后兼容)
|
|
118
|
+
export const NOTES_PATH = NOTES_DIR_PATH
|
|
119
|
+
|
|
120
|
+
// GitHub URL 常量
|
|
121
|
+
export const REPO_NOTES_URL = `https://github.com/${author}/${repoName}/tree/main/notes`
|
package/config/index.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config/index.ts
|
|
3
|
+
*
|
|
4
|
+
* 配置层统一导出
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
ConfigManager,
|
|
9
|
+
getConfigManager,
|
|
10
|
+
} from './ConfigManager'
|
|
11
|
+
export {
|
|
12
|
+
ROOT_DIR_PATH,
|
|
13
|
+
ROOT_README_PATH,
|
|
14
|
+
ROOT_TOC_PATH,
|
|
15
|
+
ROOT_CONFIG_PATH,
|
|
16
|
+
NOTES_DIR_PATH,
|
|
17
|
+
VP_SIDEBAR_PATH,
|
|
18
|
+
EOL,
|
|
19
|
+
CONSTANTS,
|
|
20
|
+
NOTES_PATH,
|
|
21
|
+
REPO_NOTES_URL,
|
|
22
|
+
port,
|
|
23
|
+
repoName,
|
|
24
|
+
} from './constants'
|
|
25
|
+
export * from './templates'
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config/templates.ts
|
|
3
|
+
*
|
|
4
|
+
* 模板定义
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 新增笔记 README.md 正文模板(不含一级标题)
|
|
9
|
+
*/
|
|
10
|
+
export const NEW_NOTES_README_MD_TEMPLATE = `
|
|
11
|
+
<!-- region:toc -->
|
|
12
|
+
|
|
13
|
+
- [1. 本节内容](#1-本节内容)
|
|
14
|
+
- [2. 评价](#2-评价)
|
|
15
|
+
|
|
16
|
+
<!-- endregion:toc -->
|
|
17
|
+
|
|
18
|
+
## 1. 本节内容
|
|
19
|
+
|
|
20
|
+
- todo
|
|
21
|
+
|
|
22
|
+
## 2. 评价
|
|
23
|
+
|
|
24
|
+
- todo
|
|
25
|
+
`
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 获取新增笔记 README.md 正文
|
|
29
|
+
*/
|
|
30
|
+
export function getNewNoteReadmeBody(): string {
|
|
31
|
+
return NEW_NOTES_README_MD_TEMPLATE
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 生成笔记一级标题
|
|
36
|
+
* @param noteIndex - 笔记索引
|
|
37
|
+
* @param title - 笔记标题
|
|
38
|
+
* @param repoUrl - 仓库URL
|
|
39
|
+
* @returns 格式化的一级标题
|
|
40
|
+
*/
|
|
41
|
+
export function generateNoteTitle(
|
|
42
|
+
noteIndex: string,
|
|
43
|
+
title: string,
|
|
44
|
+
repoUrl: string,
|
|
45
|
+
): string {
|
|
46
|
+
const dirName = `${noteIndex}. ${title}`
|
|
47
|
+
const encodedDirName = encodeURIComponent(dirName)
|
|
48
|
+
return `# [${dirName}](${repoUrl}/${encodedDirName})`
|
|
49
|
+
}
|