@tnotesjs/core 0.7.0 → 0.8.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.
- package/commands/BaseCommand.ts +58 -0
- package/commands/build/BuildCommand.ts +25 -0
- package/commands/build/PreviewCommand.ts +29 -0
- package/commands/build/index.ts +8 -0
- package/commands/dev/DevCommand.ts +75 -0
- package/commands/dev/index.ts +7 -0
- package/commands/git/PullCommand.ts +25 -0
- package/commands/git/PushCommand.ts +64 -0
- package/commands/git/index.ts +8 -0
- package/commands/index.ts +11 -0
- package/commands/init-sub-repo/InitSubRepoCommand.ts +206 -0
- package/commands/init-sub-repo/index.ts +1 -0
- package/commands/misc/HelpCommand.ts +104 -0
- package/commands/misc/index.ts +7 -0
- package/commands/models.ts +87 -0
- package/commands/note/CreateNoteCommand.ts +160 -0
- package/commands/note/RenameNoteCommand.ts +147 -0
- package/commands/note/UpdateNoteConfigCommand.ts +78 -0
- package/commands/note/index.ts +9 -0
- package/commands/registry.ts +47 -0
- package/commands/update/UpdateCommand.ts +219 -0
- package/commands/update/index.ts +7 -0
- package/commands/update-completed-count/UpdateCompletedCountCommand.ts +208 -0
- package/commands/update-completed-count/index.ts +5 -0
- package/dist/markdown/index.cjs +6 -9
- package/dist/markdown/index.js +6 -9
- package/dist/vitepress/config/index.cjs +214 -58
- package/dist/vitepress/config/index.js +208 -52
- package/markdown/components.ts +86 -0
- package/markdown/index.ts +17 -0
- package/markdown/noteFormatter.test.ts +44 -0
- package/markdown/noteFormatter.ts +237 -0
- package/package.json +7 -3
- package/vitepress/components/BilibiliOutsidePlayer/BilibiliOutsidePlayer.vue +9 -18
- package/vitepress/components/EnWordList/EnWordList.vue +16 -662
- package/vitepress/components/Footprints/Footprints.vue +15 -537
- package/vitepress/components/Mermaid/Mermaid.vue +13 -588
- package/vitepress/components/MindmapPreview/MindmapPreview.vue +12 -434
- package/vitepress/components/MindmapPreview/markdown.ts +1 -1
- package/vitepress/components/NotesTable/NotesTable.vue +11 -130
- package/vitepress/configs/markdown.config.ts +170 -26
- package/vitepress/theme/index.ts +9 -13
- package/vitepress/theme/styles/base.scss +15 -0
- package/workspace/atomic.ts +113 -0
- package/workspace/errors.ts +27 -0
- package/workspace/index.ts +40 -0
- package/workspace/mutationQueue.ts +28 -0
- package/workspace/paths.ts +64 -0
- package/workspace/reconcile.test.ts +300 -0
- package/workspace/reconcile.ts +95 -0
- package/workspace/scanner.ts +292 -0
- package/workspace/types.ts +224 -0
- package/workspace/workspace.test.ts +333 -0
- package/workspace/workspace.ts +1020 -0
- package/vitepress/components/EnWordList/RightClickMenu.vue +0 -93
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* commands/update/UpdateCommand.ts
|
|
3
|
+
*
|
|
4
|
+
* 更新命令 - 使用 ReadmeService
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs'
|
|
8
|
+
|
|
9
|
+
import { ROOT_CONFIG_PATH, ROOT_TOC_PATH, stripDeprecatedRootItemFields } from '../../config'
|
|
10
|
+
import { ReadmeService, NoteService } from '../../services'
|
|
11
|
+
import { logger, LogLevel, parseTocCompletedNotes } from '../../utils'
|
|
12
|
+
import { BaseCommand } from '../BaseCommand'
|
|
13
|
+
|
|
14
|
+
import type { TNotesConfig } from '../../types'
|
|
15
|
+
|
|
16
|
+
export class UpdateCommand extends BaseCommand {
|
|
17
|
+
private readmeService: ReadmeService
|
|
18
|
+
private noteService: NoteService
|
|
19
|
+
private quiet: boolean = false
|
|
20
|
+
|
|
21
|
+
constructor() {
|
|
22
|
+
super('update')
|
|
23
|
+
this.readmeService = ReadmeService.getInstance()
|
|
24
|
+
this.noteService = NoteService.getInstance()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 设置 quiet 模式
|
|
29
|
+
*
|
|
30
|
+
* 在 quiet 模式下,只显示 WARN 级别以上的日志
|
|
31
|
+
*/
|
|
32
|
+
setQuiet(quiet: boolean): void {
|
|
33
|
+
this.quiet = quiet
|
|
34
|
+
if (quiet) {
|
|
35
|
+
logger.setLevel(LogLevel.WARN)
|
|
36
|
+
} else {
|
|
37
|
+
logger.setLevel(LogLevel.INFO)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
protected async run(): Promise<void> {
|
|
42
|
+
await this.updateCurrentRepo()
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 更新当前知识库
|
|
47
|
+
*/
|
|
48
|
+
private async updateCurrentRepo(): Promise<void> {
|
|
49
|
+
const startTime = Date.now()
|
|
50
|
+
|
|
51
|
+
// 扫描一次笔记,复用于后续步骤
|
|
52
|
+
const notes = this.noteService.getAllNotes()
|
|
53
|
+
|
|
54
|
+
// 修正所有笔记的标题
|
|
55
|
+
if (!this.quiet) {
|
|
56
|
+
this.logger.info('正在修正笔记标题...')
|
|
57
|
+
}
|
|
58
|
+
const fixedCount = await this.noteService.fixAllNoteTitles(notes)
|
|
59
|
+
if (!this.quiet && fixedCount > 0) {
|
|
60
|
+
this.logger.success(`修正了 ${fixedCount} 个笔记标题`)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 更新知识库(传入已扫描的笔记列表,避免重复扫描)
|
|
64
|
+
await this.readmeService.updateAllReadmes({ notes })
|
|
65
|
+
|
|
66
|
+
// 更新 root_item 配置
|
|
67
|
+
await this.updateRootItem()
|
|
68
|
+
|
|
69
|
+
const duration = Date.now() - startTime
|
|
70
|
+
|
|
71
|
+
if (this.quiet) {
|
|
72
|
+
// quiet 模式:只显示简洁的完成信息
|
|
73
|
+
this.logger.success(`知识库更新完成 (${duration}ms)`)
|
|
74
|
+
} else {
|
|
75
|
+
this.logger.success('知识库更新完成')
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* 更新 root_item 配置
|
|
81
|
+
* 更新当前月份的完成笔记数量,并自动补齐从最后已有月份到当前月份之间的所有缺失月份。
|
|
82
|
+
*/
|
|
83
|
+
private async updateRootItem(): Promise<void> {
|
|
84
|
+
try {
|
|
85
|
+
// 读取当前配置
|
|
86
|
+
const configContent = readFileSync(ROOT_CONFIG_PATH, 'utf-8')
|
|
87
|
+
const config: TNotesConfig = JSON.parse(configContent)
|
|
88
|
+
|
|
89
|
+
// 1. 读取根目录 TOC.md
|
|
90
|
+
if (!existsSync(ROOT_TOC_PATH)) {
|
|
91
|
+
throw new Error('根目录 TOC.md 不存在')
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const tocContent = readFileSync(ROOT_TOC_PATH, 'utf-8')
|
|
95
|
+
|
|
96
|
+
// 2. 解析完成笔记数量
|
|
97
|
+
|
|
98
|
+
const { completedCount } = parseTocCompletedNotes(tocContent)
|
|
99
|
+
|
|
100
|
+
// 3. 生成当前月份的键名(如 '25.12')
|
|
101
|
+
const now = new Date()
|
|
102
|
+
const yearShort = String(now.getFullYear()).slice(-2)
|
|
103
|
+
const monthStr = String(now.getMonth() + 1).padStart(2, '0')
|
|
104
|
+
const currentKey = `${yearShort}.${monthStr}`
|
|
105
|
+
|
|
106
|
+
// 4. 更新完成数量,并补齐所有相邻月份之间的缺失
|
|
107
|
+
const existing = { ...(config.root_item.completed_notes_count || {}) }
|
|
108
|
+
const _countsBeforeFix = Object.keys(existing).length
|
|
109
|
+
|
|
110
|
+
existing[currentKey] = completedCount
|
|
111
|
+
const fixed = fillMissingMonthGaps(existing, currentKey)
|
|
112
|
+
|
|
113
|
+
// 5. 更新 root_item
|
|
114
|
+
config.root_item = {
|
|
115
|
+
...config.root_item,
|
|
116
|
+
completed_notes_count: fixed,
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// 删除旧字段(向后兼容)
|
|
120
|
+
delete (config.root_item as any).completed_notes_count_last_month
|
|
121
|
+
stripDeprecatedRootItemFields(
|
|
122
|
+
config.root_item as unknown as Record<string, unknown>,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
// 写入配置文件
|
|
126
|
+
writeFileSync(ROOT_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf-8')
|
|
127
|
+
|
|
128
|
+
if (!this.quiet) {
|
|
129
|
+
const filledCount = Object.keys(fixed).length - _countsBeforeFix
|
|
130
|
+
const filledMsg = filledCount > 0 ? `,补齐 ${filledCount} 个缺失月份` : ''
|
|
131
|
+
this.logger.success(
|
|
132
|
+
`root_item 配置已更新: ${currentKey} 月完成 ${completedCount} 篇笔记${filledMsg}`,
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
} catch (error) {
|
|
136
|
+
if (!this.quiet) {
|
|
137
|
+
this.logger.error(
|
|
138
|
+
`更新 root_item 失败: ${
|
|
139
|
+
error instanceof Error ? error.message : String(error)
|
|
140
|
+
}`,
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
throw error
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 补齐 completed_notes_count 中所有相邻月份之间的缺口
|
|
150
|
+
* 遍历排序后的所有 key,发现非连续的月份就插入前一个月份的值
|
|
151
|
+
*/
|
|
152
|
+
function fillMissingMonthGaps(
|
|
153
|
+
counts: Record<string, number>,
|
|
154
|
+
currentKey: string,
|
|
155
|
+
): Record<string, number> {
|
|
156
|
+
const existingKeys = Object.keys(counts).sort()
|
|
157
|
+
const result: Record<string, number> = {}
|
|
158
|
+
|
|
159
|
+
// 将 currentKey 加入集合以确保覆盖到当前月
|
|
160
|
+
const keySet = new Set(existingKeys)
|
|
161
|
+
keySet.add(currentKey)
|
|
162
|
+
const allKeys = Array.from(keySet).sort()
|
|
163
|
+
|
|
164
|
+
let prevValue = 0
|
|
165
|
+
let lastKey: string | null = null
|
|
166
|
+
|
|
167
|
+
for (const key of allKeys) {
|
|
168
|
+
if (lastKey !== null) {
|
|
169
|
+
// 检查 lastKey 和 key 之间是否有缺口
|
|
170
|
+
const missing = generateMissingMonthKeys(lastKey, key)
|
|
171
|
+
for (const midKey of missing) {
|
|
172
|
+
result[midKey] = prevValue
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
result[key] = counts[key] ?? prevValue
|
|
176
|
+
prevValue = result[key]
|
|
177
|
+
lastKey = key
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return result
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* 生成两个 YY.MM 格式月份键之间的所有缺失月份键(不含两端)
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* generateMissingMonthKeys('26.04', '26.06') // => ['26.05']
|
|
188
|
+
* generateMissingMonthKeys('25.12', '26.02') // => ['26.01']
|
|
189
|
+
* generateMissingMonthKeys('26.04', '26.04') // => []
|
|
190
|
+
*/
|
|
191
|
+
function generateMissingMonthKeys(fromKey: string, toKey: string): string[] {
|
|
192
|
+
const parseKey = (key: string) => {
|
|
193
|
+
const [yy, mm] = key.split('.').map(Number)
|
|
194
|
+
return { year: 2000 + yy, month: mm }
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const from = parseKey(fromKey)
|
|
198
|
+
const to = parseKey(toKey)
|
|
199
|
+
|
|
200
|
+
const missing: string[] = []
|
|
201
|
+
let year = from.year
|
|
202
|
+
let month = from.month
|
|
203
|
+
|
|
204
|
+
while (true) {
|
|
205
|
+
month++
|
|
206
|
+
if (month > 12) { month = 1; year++ }
|
|
207
|
+
|
|
208
|
+
const shortYear = String(year).slice(-2)
|
|
209
|
+
const paddedMonth = String(month).padStart(2, '0')
|
|
210
|
+
const candidateKey = `${shortYear}.${paddedMonth}`
|
|
211
|
+
|
|
212
|
+
if (candidateKey === toKey) break
|
|
213
|
+
if (year > to.year || (year === to.year && month > to.month)) break
|
|
214
|
+
|
|
215
|
+
missing.push(candidateKey)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return missing
|
|
219
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* commands/update-completed-count/UpdateCompletedCountCommand.ts
|
|
3
|
+
*
|
|
4
|
+
* 更新完成笔记数量历史记录命令
|
|
5
|
+
* 基于 Git 历史统计最近 12 个月(近 1 年)的每月完成笔记数量
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { execSync } from 'child_process'
|
|
9
|
+
import { readFileSync, writeFileSync } from 'fs'
|
|
10
|
+
|
|
11
|
+
import { ROOT_DIR_PATH, ROOT_CONFIG_PATH, stripDeprecatedRootItemFields } from '../../config'
|
|
12
|
+
import { parseReadmeCompletedNotes, parseTocCompletedNotes } from '../../utils'
|
|
13
|
+
import { BaseCommand } from '../BaseCommand'
|
|
14
|
+
|
|
15
|
+
import type { TNotesConfig } from '../../types'
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
export class UpdateCompletedCountCommand extends BaseCommand {
|
|
20
|
+
constructor() {
|
|
21
|
+
super('update-completed-count')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
protected async run(): Promise<void> {
|
|
25
|
+
await this.updateCurrentRepo()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 更新当前知识库
|
|
30
|
+
*/
|
|
31
|
+
private async updateCurrentRepo(): Promise<void> {
|
|
32
|
+
const startTime = Date.now()
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
// 读取当前配置
|
|
36
|
+
const configContent = readFileSync(ROOT_CONFIG_PATH, 'utf-8')
|
|
37
|
+
const config: TNotesConfig = JSON.parse(configContent)
|
|
38
|
+
|
|
39
|
+
this.logger.info('开始更新完成笔记数量历史记录...')
|
|
40
|
+
|
|
41
|
+
// 计算所有月份的完成笔记数量
|
|
42
|
+
const completedNotesCountHistory =
|
|
43
|
+
await this.getCompletedNotesCountHistory()
|
|
44
|
+
|
|
45
|
+
// 更新配置
|
|
46
|
+
config.root_item = {
|
|
47
|
+
...config.root_item,
|
|
48
|
+
completed_notes_count: completedNotesCountHistory,
|
|
49
|
+
}
|
|
50
|
+
stripDeprecatedRootItemFields(
|
|
51
|
+
config.root_item as unknown as Record<string, unknown>,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
// 写入配置文件
|
|
55
|
+
writeFileSync(ROOT_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf-8')
|
|
56
|
+
|
|
57
|
+
const duration = Date.now() - startTime
|
|
58
|
+
const monthKeys = Object.keys(completedNotesCountHistory)
|
|
59
|
+
const currentKey = monthKeys[monthKeys.length - 1]
|
|
60
|
+
const currentCount = completedNotesCountHistory[currentKey] || 0
|
|
61
|
+
|
|
62
|
+
this.logger.success(
|
|
63
|
+
`历史数据更新完成: 共 ${monthKeys.length} 个月, 当前 ${currentKey} 月完成 ${currentCount} 篇笔记 (${duration}ms)`,
|
|
64
|
+
)
|
|
65
|
+
} catch (error) {
|
|
66
|
+
this.logger.error(
|
|
67
|
+
`更新失败: ${error instanceof Error ? error.message : String(error)}`,
|
|
68
|
+
)
|
|
69
|
+
throw error
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 获取历史每个月的 completed_notes_count(最近12个月)
|
|
75
|
+
*
|
|
76
|
+
* 逻辑:
|
|
77
|
+
* 1. 计算最近12个月的范围(当前月份往前推11个月)
|
|
78
|
+
* 2. 遍历这12个月,从 Git 历史中读取 TOC.md(回退 README.md)
|
|
79
|
+
* 3. 解析获取完成笔记数量
|
|
80
|
+
* 4. 返回对象 { '25.01': 0, '25.02': 1, ..., '25.12': 15 }
|
|
81
|
+
*/
|
|
82
|
+
private async getCompletedNotesCountHistory(): Promise<
|
|
83
|
+
Record<string, number>
|
|
84
|
+
> {
|
|
85
|
+
try {
|
|
86
|
+
// 1. 计算最近12个月的范围
|
|
87
|
+
const now = new Date()
|
|
88
|
+
const currentYear = now.getFullYear()
|
|
89
|
+
const currentMonth = now.getMonth() // 0-11 (0=January, 11=December)
|
|
90
|
+
|
|
91
|
+
// 计算第一个月(当前月往前推11个月)
|
|
92
|
+
// 例如:当前是 2025年12月(11),往前推11个月 => 2025年1月(0)
|
|
93
|
+
let firstYear = currentYear
|
|
94
|
+
let firstMonth = currentMonth - 11
|
|
95
|
+
|
|
96
|
+
// 处理跨年情况
|
|
97
|
+
if (firstMonth < 0) {
|
|
98
|
+
firstYear = currentYear - 1
|
|
99
|
+
firstMonth = 12 + firstMonth
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const result: Record<string, number> = {}
|
|
103
|
+
let prevCount = 0
|
|
104
|
+
|
|
105
|
+
// 2. 遍历最近12个月
|
|
106
|
+
for (let i = 0; i < 12; i++) {
|
|
107
|
+
const targetYear = firstYear + Math.floor((firstMonth + i) / 12)
|
|
108
|
+
const targetMonth = (firstMonth + i) % 12
|
|
109
|
+
|
|
110
|
+
// 生成键名 (如 '25.01', '25.12')
|
|
111
|
+
const yearShort = String(targetYear).slice(-2)
|
|
112
|
+
const monthStr = String(targetMonth + 1).padStart(2, '0')
|
|
113
|
+
const key = `${yearShort}.${monthStr}`
|
|
114
|
+
|
|
115
|
+
// 尝试从 Git 历史获取
|
|
116
|
+
try {
|
|
117
|
+
const count = await this.getMonthCompletedCount(
|
|
118
|
+
targetYear,
|
|
119
|
+
targetMonth,
|
|
120
|
+
prevCount,
|
|
121
|
+
)
|
|
122
|
+
result[key] = count
|
|
123
|
+
prevCount = count
|
|
124
|
+
this.logger.info(`✓ ${key}: ${count} 篇`)
|
|
125
|
+
} catch (error) {
|
|
126
|
+
// 该月没有提交或解析失败,使用上一个月的值
|
|
127
|
+
result[key] = prevCount
|
|
128
|
+
this.logger.warn(`${key}: 无数据,使用 ${prevCount}(上月值)`)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return result
|
|
133
|
+
} catch (error) {
|
|
134
|
+
this.logger.error(
|
|
135
|
+
`获取历史数据失败: ${
|
|
136
|
+
error instanceof Error ? error.message : String(error)
|
|
137
|
+
}`,
|
|
138
|
+
)
|
|
139
|
+
return {}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* 获取指定月份的完成笔记数量
|
|
145
|
+
* @param year - 年份
|
|
146
|
+
* @param month - 月份 (0-11)
|
|
147
|
+
* @param fallbackCount - 回退值(如果该月没有数据)
|
|
148
|
+
* @returns 完成笔记数量
|
|
149
|
+
*/
|
|
150
|
+
private async getMonthCompletedCount(
|
|
151
|
+
year: number,
|
|
152
|
+
month: number,
|
|
153
|
+
fallbackCount: number = 0,
|
|
154
|
+
): Promise<number> {
|
|
155
|
+
// 计算该月的最后一天
|
|
156
|
+
const lastDayOfMonth = new Date(year, month + 1, 0, 23, 59, 59)
|
|
157
|
+
const yearStr = lastDayOfMonth.getFullYear()
|
|
158
|
+
const monthStr = String(lastDayOfMonth.getMonth() + 1).padStart(2, '0')
|
|
159
|
+
const dayStr = String(lastDayOfMonth.getDate()).padStart(2, '0')
|
|
160
|
+
const untilDate = `${yearStr}-${monthStr}-${dayStr} 23:59:59 +0800`
|
|
161
|
+
|
|
162
|
+
// 查找该月最后一次修改 TOC.md 或 README.md 的提交
|
|
163
|
+
let commitHash = execSync(
|
|
164
|
+
`git log --until="${untilDate}" --format=%H -1 -- TOC.md`,
|
|
165
|
+
{
|
|
166
|
+
cwd: ROOT_DIR_PATH,
|
|
167
|
+
encoding: 'utf-8',
|
|
168
|
+
},
|
|
169
|
+
).trim()
|
|
170
|
+
|
|
171
|
+
let filePath = 'TOC.md'
|
|
172
|
+
|
|
173
|
+
if (!commitHash) {
|
|
174
|
+
commitHash = execSync(
|
|
175
|
+
`git log --until="${untilDate}" --format=%H -1 -- README.md`,
|
|
176
|
+
{
|
|
177
|
+
cwd: ROOT_DIR_PATH,
|
|
178
|
+
encoding: 'utf-8',
|
|
179
|
+
},
|
|
180
|
+
).trim()
|
|
181
|
+
filePath = 'README.md'
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (!commitHash) {
|
|
185
|
+
// 该月没有提交,返回回退值
|
|
186
|
+
return fallbackCount
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// 读取该提交中的文件内容
|
|
190
|
+
let fileContent: string
|
|
191
|
+
try {
|
|
192
|
+
fileContent = execSync(`git show ${commitHash}:${filePath}`, {
|
|
193
|
+
cwd: ROOT_DIR_PATH,
|
|
194
|
+
encoding: 'utf-8',
|
|
195
|
+
})
|
|
196
|
+
} catch (error) {
|
|
197
|
+
// 文件在该提交中不存在
|
|
198
|
+
return fallbackCount
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// 解析完成笔记数量
|
|
202
|
+
const { completedCount } =
|
|
203
|
+
filePath === 'TOC.md'
|
|
204
|
+
? parseTocCompletedNotes(fileContent)
|
|
205
|
+
: parseReadmeCompletedNotes(fileContent)
|
|
206
|
+
return completedCount
|
|
207
|
+
}
|
|
208
|
+
}
|
package/dist/markdown/index.cjs
CHANGED
|
@@ -7,26 +7,22 @@ var _chunk7FEANCT6cjs = require('../chunk-7FEANCT6.cjs');
|
|
|
7
7
|
// markdown/components.ts
|
|
8
8
|
var TNOTES_COMPONENTS = [
|
|
9
9
|
{
|
|
10
|
-
name: "
|
|
11
|
-
aliases: ["B"],
|
|
10
|
+
name: "BilibiliVideo",
|
|
12
11
|
kind: "block-component",
|
|
13
12
|
editable: "visual"
|
|
14
13
|
},
|
|
15
14
|
{
|
|
16
|
-
name: "
|
|
17
|
-
aliases: ["E"],
|
|
15
|
+
name: "WordList",
|
|
18
16
|
kind: "block-component",
|
|
19
17
|
editable: "visual"
|
|
20
18
|
},
|
|
21
19
|
{
|
|
22
20
|
name: "Footprints",
|
|
23
|
-
aliases: ["F"],
|
|
24
21
|
kind: "block-component",
|
|
25
22
|
editable: "visual"
|
|
26
23
|
},
|
|
27
24
|
{
|
|
28
25
|
name: "NotesTable",
|
|
29
|
-
aliases: ["N"],
|
|
30
26
|
kind: "block-component",
|
|
31
27
|
editable: "visual"
|
|
32
28
|
},
|
|
@@ -36,7 +32,8 @@ var TNOTES_COMPONENTS = [
|
|
|
36
32
|
editable: "visual"
|
|
37
33
|
},
|
|
38
34
|
{
|
|
39
|
-
name: "
|
|
35
|
+
name: "Mindmap",
|
|
36
|
+
aliases: ["MindmapPreview"],
|
|
40
37
|
kind: "block-component",
|
|
41
38
|
editable: "visual"
|
|
42
39
|
},
|
|
@@ -57,14 +54,14 @@ var TNOTES_COMPONENTS = [
|
|
|
57
54
|
},
|
|
58
55
|
{ name: "swiper", kind: "container", editable: "visual" },
|
|
59
56
|
{ name: "code-group", kind: "container", editable: "visual" },
|
|
57
|
+
{ name: "footprints", kind: "container", editable: "visual" },
|
|
60
58
|
{ name: "details", kind: "container", editable: "visual" },
|
|
61
59
|
{ name: "info", kind: "container", editable: "visual" },
|
|
62
60
|
{ name: "tip", kind: "container", editable: "visual" },
|
|
63
61
|
{ name: "warning", kind: "container", editable: "visual" },
|
|
64
62
|
{ name: "danger", kind: "container", editable: "visual" },
|
|
65
63
|
{ name: "mermaid", kind: "fenced-language", editable: "visual" },
|
|
66
|
-
{ name: "mindmap", kind: "fenced-language", editable: "visual" }
|
|
67
|
-
{ name: "markmap", kind: "fenced-language", editable: "visual" }
|
|
64
|
+
{ name: "mindmap", kind: "fenced-language", editable: "visual" }
|
|
68
65
|
];
|
|
69
66
|
function findTNotesComponent(name) {
|
|
70
67
|
const normalized = name.toLowerCase();
|
package/dist/markdown/index.js
CHANGED
|
@@ -7,26 +7,22 @@ import {
|
|
|
7
7
|
// markdown/components.ts
|
|
8
8
|
var TNOTES_COMPONENTS = [
|
|
9
9
|
{
|
|
10
|
-
name: "
|
|
11
|
-
aliases: ["B"],
|
|
10
|
+
name: "BilibiliVideo",
|
|
12
11
|
kind: "block-component",
|
|
13
12
|
editable: "visual"
|
|
14
13
|
},
|
|
15
14
|
{
|
|
16
|
-
name: "
|
|
17
|
-
aliases: ["E"],
|
|
15
|
+
name: "WordList",
|
|
18
16
|
kind: "block-component",
|
|
19
17
|
editable: "visual"
|
|
20
18
|
},
|
|
21
19
|
{
|
|
22
20
|
name: "Footprints",
|
|
23
|
-
aliases: ["F"],
|
|
24
21
|
kind: "block-component",
|
|
25
22
|
editable: "visual"
|
|
26
23
|
},
|
|
27
24
|
{
|
|
28
25
|
name: "NotesTable",
|
|
29
|
-
aliases: ["N"],
|
|
30
26
|
kind: "block-component",
|
|
31
27
|
editable: "visual"
|
|
32
28
|
},
|
|
@@ -36,7 +32,8 @@ var TNOTES_COMPONENTS = [
|
|
|
36
32
|
editable: "visual"
|
|
37
33
|
},
|
|
38
34
|
{
|
|
39
|
-
name: "
|
|
35
|
+
name: "Mindmap",
|
|
36
|
+
aliases: ["MindmapPreview"],
|
|
40
37
|
kind: "block-component",
|
|
41
38
|
editable: "visual"
|
|
42
39
|
},
|
|
@@ -57,14 +54,14 @@ var TNOTES_COMPONENTS = [
|
|
|
57
54
|
},
|
|
58
55
|
{ name: "swiper", kind: "container", editable: "visual" },
|
|
59
56
|
{ name: "code-group", kind: "container", editable: "visual" },
|
|
57
|
+
{ name: "footprints", kind: "container", editable: "visual" },
|
|
60
58
|
{ name: "details", kind: "container", editable: "visual" },
|
|
61
59
|
{ name: "info", kind: "container", editable: "visual" },
|
|
62
60
|
{ name: "tip", kind: "container", editable: "visual" },
|
|
63
61
|
{ name: "warning", kind: "container", editable: "visual" },
|
|
64
62
|
{ name: "danger", kind: "container", editable: "visual" },
|
|
65
63
|
{ name: "mermaid", kind: "fenced-language", editable: "visual" },
|
|
66
|
-
{ name: "mindmap", kind: "fenced-language", editable: "visual" }
|
|
67
|
-
{ name: "markmap", kind: "fenced-language", editable: "visual" }
|
|
64
|
+
{ name: "mindmap", kind: "fenced-language", editable: "visual" }
|
|
68
65
|
];
|
|
69
66
|
function findTNotesComponent(name) {
|
|
70
67
|
const normalized = name.toLowerCase();
|