@tnotesjs/core 0.0.7 → 0.1.14
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/README.md +6 -3
- package/dist/{chunk-JDVN2QYW.js → chunk-FVKQPBPP.js} +643 -546
- package/dist/{chunk-NASIL5FY.js → chunk-SQVHJR2Z.js} +0 -4
- package/dist/cli/index.js +126 -126
- package/dist/index.js +1 -1
- package/dist/vitepress/config/index.js +229 -208
- package/package.json +16 -3
- package/types/shims.d.ts +3 -4
- package/vitepress/components/CodeBlockFullscreen/CodeBlockFullscreen.vue +2 -1
- package/vitepress/components/CodeBlockFullscreen/index.ts +2 -1
- package/vitepress/components/Discussions/Discussions.vue +3 -2
- package/vitepress/components/EnWordList/EnWordList.vue +2 -1
- package/vitepress/components/Layout/AboutModal.vue +1 -1
- package/vitepress/components/Layout/AboutPanel.vue +8 -3
- package/vitepress/components/Layout/ContentCollapse.vue +2 -1
- package/vitepress/components/Layout/CustomSidebar.vue +7 -4
- package/vitepress/components/Layout/DocBeforeControls.vue +4 -4
- package/vitepress/components/Layout/DocFooter.vue +2 -1
- package/vitepress/components/Layout/ImagePreview.vue +2 -1
- package/vitepress/components/Layout/Layout.vue +38 -20
- package/vitepress/components/Layout/NoteStatus.vue +2 -1
- package/vitepress/components/Layout/SidebarItems.vue +7 -2
- package/vitepress/components/Layout/SidebarNavBefore.vue +22 -0
- package/vitepress/components/Layout/ToggleFullContent.vue +2 -1
- package/vitepress/components/Layout/ToggleSidebar.vue +2 -1
- package/vitepress/components/Layout/composables/useCollapseControl.ts +1 -1
- package/vitepress/components/Layout/composables/useNoteConfig.ts +2 -4
- package/vitepress/components/Layout/composables/useNoteSave.ts +23 -18
- package/vitepress/components/Layout/composables/useRedirect.ts +8 -5
- package/vitepress/components/Layout/composables/useRenameOverlay.ts +33 -0
- package/vitepress/components/Layout/composables/useRenameRedirect.ts +59 -0
- package/vitepress/components/Layout/composables/useVSCodeIntegration.ts +7 -4
- package/vitepress/components/Layout/homeReadme.data.ts +1 -1
- package/vitepress/components/LoadingPage/LoadingPage.vue +84 -192
- package/vitepress/components/MarkMap/MarkMap.vue +5 -4
- package/vitepress/components/Mermaid/Mermaid.vue +4 -2
- package/vitepress/components/NotesTable/NotesTable.vue +2 -1
- package/vitepress/components/Settings/Settings.vue +2 -1
- package/vitepress/components/Settings/SettingsDialog.vue +243 -0
- package/vitepress/components/Settings/composables/useSettingsDialog.ts +35 -0
- package/vitepress/components/SidebarCard/MindMapView.vue +10 -9
- package/vitepress/components/SidebarCard/SidebarCard.vue +12 -14
- package/vitepress/config/index.ts +11 -4
- package/vitepress/configs/head.config.ts +2 -1
- package/vitepress/configs/markdown-it.d.ts +6 -3
- package/vitepress/configs/markdown.config.ts +6 -5
- package/vitepress/configs/theme.config.ts +1 -1
- package/vitepress/plugins/buildProgressPlugin.ts +2 -38
- package/vitepress/plugins/fileWatcherBridgePlugin.ts +49 -0
- package/vitepress/plugins/getNoteByConfigIdPlugin.ts +3 -2
- package/vitepress/plugins/renameNotePlugin.ts +9 -1
- package/vitepress/plugins/updateConfigPlugin.ts +2 -1
- package/vitepress/theme/index.ts +45 -3
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { useData } from 'vitepress'
|
|
3
|
-
import { formatDate } from '../utils.ts'
|
|
4
3
|
import { ref, computed, watch } from 'vue'
|
|
5
|
-
import { useRouter } from 'vitepress'
|
|
6
|
-
// @ts-expect-error - VitePress Data Loader
|
|
7
|
-
import { data as sidebarConfig } from '../sidebar.data'
|
|
8
|
-
|
|
9
|
-
import { NOTES_DIR_KEY, REPO_NAME, AUTHOR, ROOT_ITEM } from '../constants.ts'
|
|
10
|
-
|
|
11
|
-
import MindMapView from './MindMapView.vue'
|
|
12
|
-
import NotesTrendChart from './NotesTrendChart.vue'
|
|
13
4
|
|
|
14
5
|
import {
|
|
15
6
|
icon__fold,
|
|
@@ -21,6 +12,13 @@ import {
|
|
|
21
12
|
icon__number_gray,
|
|
22
13
|
icon__number_purple,
|
|
23
14
|
} from '../../assets/icons'
|
|
15
|
+
import { NOTES_DIR_KEY, REPO_NAME, AUTHOR, ROOT_ITEM } from '../constants.ts'
|
|
16
|
+
import { useSettingsDialog } from '../Settings/composables/useSettingsDialog'
|
|
17
|
+
import { data as sidebarConfig } from '../sidebar.data'
|
|
18
|
+
import { formatDate } from '../utils.ts'
|
|
19
|
+
// @ts-expect-error - VitePress Data Loader
|
|
20
|
+
import MindMapView from './MindMapView.vue'
|
|
21
|
+
import NotesTrendChart from './NotesTrendChart.vue'
|
|
24
22
|
|
|
25
23
|
// #region props
|
|
26
24
|
const props = defineProps({
|
|
@@ -99,7 +97,7 @@ const folderViewData = computed(() => {
|
|
|
99
97
|
})
|
|
100
98
|
// #endregion
|
|
101
99
|
|
|
102
|
-
const
|
|
100
|
+
const { open: openSettings } = useSettingsDialog()
|
|
103
101
|
const { site } = useData()
|
|
104
102
|
const baseUrl = site.value.base.replace(/\/$/, '')
|
|
105
103
|
|
|
@@ -263,10 +261,10 @@ function openVSCodeRepo() {
|
|
|
263
261
|
|
|
264
262
|
if (!notesDir) {
|
|
265
263
|
const shouldRedirect = confirm(
|
|
266
|
-
'
|
|
264
|
+
'请先配置本地知识库所在位置,点击确定打开设置面板',
|
|
267
265
|
)
|
|
268
266
|
if (shouldRedirect) {
|
|
269
|
-
|
|
267
|
+
openSettings()
|
|
270
268
|
}
|
|
271
269
|
return
|
|
272
270
|
}
|
|
@@ -280,10 +278,10 @@ function openVSCodeArticle(article) {
|
|
|
280
278
|
|
|
281
279
|
if (!notesDir) {
|
|
282
280
|
const shouldRedirect = confirm(
|
|
283
|
-
'
|
|
281
|
+
'请先配置本地知识库所在位置,点击确定打开设置面板',
|
|
284
282
|
)
|
|
285
283
|
if (shouldRedirect) {
|
|
286
|
-
|
|
284
|
+
openSettings()
|
|
287
285
|
}
|
|
288
286
|
return
|
|
289
287
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import fs from 'fs'
|
|
11
11
|
import path from 'path'
|
|
12
12
|
import { defineConfig, type UserConfig } from 'vitepress'
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
import {
|
|
15
15
|
getIgnoreList,
|
|
16
16
|
getGithubPageUrl,
|
|
@@ -18,10 +18,13 @@ import {
|
|
|
18
18
|
getMarkdownConfig,
|
|
19
19
|
getThemeConfig,
|
|
20
20
|
} from '../configs'
|
|
21
|
-
import { updateConfigPlugin } from '../plugins/updateConfigPlugin'
|
|
22
|
-
import { renameNotePlugin } from '../plugins/renameNotePlugin'
|
|
23
|
-
import { getNoteByConfigIdPlugin } from '../plugins/getNoteByConfigIdPlugin'
|
|
24
21
|
import { buildProgressPlugin } from '../plugins/buildProgressPlugin'
|
|
22
|
+
import { fileWatcherBridgePlugin } from '../plugins/fileWatcherBridgePlugin'
|
|
23
|
+
import { getNoteByConfigIdPlugin } from '../plugins/getNoteByConfigIdPlugin'
|
|
24
|
+
import { renameNotePlugin } from '../plugins/renameNotePlugin'
|
|
25
|
+
import { updateConfigPlugin } from '../plugins/updateConfigPlugin'
|
|
26
|
+
|
|
27
|
+
import type { TNotesConfig } from '../../types'
|
|
25
28
|
|
|
26
29
|
/**
|
|
27
30
|
* 读取 .tnotes.json 配置文件
|
|
@@ -75,9 +78,13 @@ export function defineNotesConfig(overrides: UserConfig = {}) {
|
|
|
75
78
|
updateConfigPlugin() as any,
|
|
76
79
|
renameNotePlugin() as any,
|
|
77
80
|
getNoteByConfigIdPlugin() as any,
|
|
81
|
+
fileWatcherBridgePlugin() as any,
|
|
78
82
|
...(overrideVite?.plugins || []),
|
|
79
83
|
],
|
|
80
84
|
server: {
|
|
85
|
+
// 显式同时监听 IPv4 / IPv6,避免 Node 18+ 在 Windows 下偶发只绑定 ::1
|
|
86
|
+
// 导致 Chrome 解析 localhost → 127.0.0.1 时连接被拒、页面一直 pending。
|
|
87
|
+
// host: true,
|
|
81
88
|
watch: {
|
|
82
89
|
ignored: IGNORE_LIST,
|
|
83
90
|
},
|
|
@@ -5,19 +5,22 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
declare module 'markdown-it-container' {
|
|
8
|
-
import { PluginWithOptions } from 'markdown-it'
|
|
8
|
+
import { PluginWithOptions } from 'markdown-it'
|
|
9
|
+
|
|
9
10
|
const markdownItContainer: PluginWithOptions<any>
|
|
10
11
|
export default markdownItContainer
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
declare module 'markdown-it-link-attributes' {
|
|
14
|
-
import { PluginWithOptions } from 'markdown-it'
|
|
15
|
+
import { PluginWithOptions } from 'markdown-it'
|
|
16
|
+
|
|
15
17
|
const markdownItLinkAttributes: PluginWithOptions<any>
|
|
16
18
|
export default markdownItLinkAttributes
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
declare module 'markdown-it-task-lists' {
|
|
20
|
-
import { PluginWithOptions } from 'markdown-it'
|
|
22
|
+
import { PluginWithOptions } from 'markdown-it'
|
|
23
|
+
|
|
21
24
|
const markdownItTaskLists: PluginWithOptions<any>
|
|
22
25
|
export default markdownItTaskLists
|
|
23
26
|
}
|
|
@@ -3,14 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Markdown 配置
|
|
5
5
|
*/
|
|
6
|
+
import fs from 'fs'
|
|
6
7
|
import MarkdownIt from 'markdown-it'
|
|
7
8
|
import markdownItContainer from 'markdown-it-container'
|
|
8
9
|
import mila from 'markdown-it-link-attributes'
|
|
9
10
|
import markdownItTaskLists from 'markdown-it-task-lists'
|
|
10
|
-
import { MarkdownOptions } from 'vitepress'
|
|
11
|
-
import { generateAnchor } from '../../utils'
|
|
12
|
-
import fs from 'fs'
|
|
13
11
|
import path from 'path'
|
|
12
|
+
import { MarkdownOptions } from 'vitepress'
|
|
13
|
+
|
|
14
|
+
import { generateAnchor } from '../../utils'
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* 辅助函数:HTML 转义
|
|
@@ -105,7 +106,7 @@ function configureMarkMapContainer(md: MarkdownIt) {
|
|
|
105
106
|
const endLine = open.map ? open.map[1] - 1 : null
|
|
106
107
|
|
|
107
108
|
// 1) 从开头 fence 行解析参数(支持 `{a=1 b="x"}`、`a=1 b="x"`,并支持单个数字 shorthand)
|
|
108
|
-
|
|
109
|
+
const params: { [key: string]: any; initialExpandLevel?: number } = {}
|
|
109
110
|
|
|
110
111
|
if (open.map && typeof open.map[0] === 'number') {
|
|
111
112
|
const openLine = (lines[open.map[0]] || '').trim()
|
|
@@ -179,7 +180,7 @@ function configureMarkMapContainer(md: MarkdownIt) {
|
|
|
179
180
|
const refMatch = firstNonEmptyLine.trim().match(/^<<<\s*(.+)$/)
|
|
180
181
|
if (refMatch) {
|
|
181
182
|
// 提取引用路径,支持引号包裹
|
|
182
|
-
|
|
183
|
+
const refRaw = refMatch[1].trim().replace(/^['"]|['"]$/g, '')
|
|
183
184
|
|
|
184
185
|
// 尝试同步读取文件内容(兼容常见 Node 环境)
|
|
185
186
|
try {
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* doc:
|
|
7
7
|
* https://vitepress.dev/reference/default-theme-config
|
|
8
8
|
*/
|
|
9
|
-
import type { DefaultTheme } from 'vitepress'
|
|
10
9
|
import type { TNotesConfig } from '../../types'
|
|
10
|
+
import type { DefaultTheme } from 'vitepress'
|
|
11
11
|
|
|
12
12
|
export function getThemeConfig(config: TNotesConfig): DefaultTheme.Config {
|
|
13
13
|
const themeConfig: DefaultTheme.Config = {
|
|
@@ -7,16 +7,16 @@
|
|
|
7
7
|
* https://github.com/jeddygong/vite-plugin-progress
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import type { Plugin } from 'vite'
|
|
11
10
|
import {
|
|
12
11
|
existsSync,
|
|
13
12
|
readFileSync,
|
|
14
13
|
writeFileSync,
|
|
15
14
|
mkdirSync,
|
|
16
|
-
readdirSync,
|
|
17
15
|
} from 'fs'
|
|
18
16
|
import { join } from 'path'
|
|
19
17
|
|
|
18
|
+
import type { Plugin } from 'vite'
|
|
19
|
+
|
|
20
20
|
/** 缓存目录和文件路径 */
|
|
21
21
|
const CACHE_DIR = join(process.cwd(), 'node_modules', '.tnotes-progress')
|
|
22
22
|
const CACHE_FILE = join(CACHE_DIR, 'build-cache.json')
|
|
@@ -64,37 +64,6 @@ function setCacheData(data: CacheData): void {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
/**
|
|
68
|
-
* 扫描源目录文件数量
|
|
69
|
-
*/
|
|
70
|
-
function countSourceFiles(srcDir: string): number {
|
|
71
|
-
let count = 0
|
|
72
|
-
const extensions = /\.(vue|ts|js|jsx|tsx|css|scss|sass|styl|less|md)$/i
|
|
73
|
-
|
|
74
|
-
const scan = (dir: string) => {
|
|
75
|
-
try {
|
|
76
|
-
const entries = readdirSync(dir, { withFileTypes: true })
|
|
77
|
-
for (const entry of entries) {
|
|
78
|
-
const fullPath = join(dir, entry.name)
|
|
79
|
-
if (
|
|
80
|
-
entry.isDirectory() &&
|
|
81
|
-
!entry.name.startsWith('.') &&
|
|
82
|
-
entry.name !== 'node_modules'
|
|
83
|
-
) {
|
|
84
|
-
scan(fullPath)
|
|
85
|
-
} else if (entry.isFile() && extensions.test(entry.name)) {
|
|
86
|
-
count++
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
} catch {
|
|
90
|
-
// 忽略错误
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
scan(srcDir)
|
|
95
|
-
return count
|
|
96
|
-
}
|
|
97
|
-
|
|
98
67
|
// ============ 全局状态 ============
|
|
99
68
|
let globalStartTime = 0
|
|
100
69
|
let globalTransformCount = 0
|
|
@@ -103,7 +72,6 @@ let globalHasError = false
|
|
|
103
72
|
let globalIsBuilding = false
|
|
104
73
|
let globalOutDir = ''
|
|
105
74
|
let globalLastPercent = 0
|
|
106
|
-
let globalFileCount = 0
|
|
107
75
|
let globalLastLoggedPercent = -1 // 非 TTY 环境下上次输出的百分比区间,初始为 -1 以便第一次输出
|
|
108
76
|
let globalLastOutputTime = 0 // 非 TTY 环境下上次输出时间戳,用于时间节流
|
|
109
77
|
let globalTransformEndTime = 0 // transform 阶段结束时间戳
|
|
@@ -273,10 +241,6 @@ export function buildProgressPlugin(
|
|
|
273
241
|
globalLastHookTime = Date.now()
|
|
274
242
|
globalOutDir = config.build?.outDir || 'dist'
|
|
275
243
|
|
|
276
|
-
if (!hasCache) {
|
|
277
|
-
globalFileCount = countSourceFiles(process.cwd())
|
|
278
|
-
}
|
|
279
|
-
|
|
280
244
|
interceptOutput()
|
|
281
245
|
|
|
282
246
|
// 停滞填充计时器:当 Vite hook 超过 2 秒没触发时(如 VitePress 渲染页面阶段),
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* .vitepress/tnotes/vitepress/plugins/fileWatcherBridgePlugin.ts
|
|
3
|
+
*
|
|
4
|
+
* file-watcher 与浏览器之间的 IPC 桥。
|
|
5
|
+
*
|
|
6
|
+
* file-watcher 跑在 DevCommand 主进程,VitePress / Vite 跑在子进程,
|
|
7
|
+
* 两者无法共享单例。文件夹直接重命名后,file-watcher 会 fetch 本接口,
|
|
8
|
+
* 本接口调 `server.ws.send` 向浏览器广播 `tnotes:note-renamed`。
|
|
9
|
+
*/
|
|
10
|
+
import type { PluginOption } from 'vite'
|
|
11
|
+
|
|
12
|
+
const RENAME_EVENT = 'tnotes:note-renamed'
|
|
13
|
+
const BROADCAST_PATH = '/__tnotes_broadcast_rename'
|
|
14
|
+
|
|
15
|
+
export function fileWatcherBridgePlugin(): PluginOption {
|
|
16
|
+
return {
|
|
17
|
+
name: 'tnotes-file-watcher-bridge',
|
|
18
|
+
apply: 'serve',
|
|
19
|
+
configureServer(server) {
|
|
20
|
+
server.middlewares.use((req, res, next) => {
|
|
21
|
+
// Vite 的 baseMiddleware 顺序在不同版本可能不同,
|
|
22
|
+
// 这里同时接受 `/__tnotes_broadcast_rename` 与带 base 前缀的路径。
|
|
23
|
+
const url = req.url ?? ''
|
|
24
|
+
const isBroadcast =
|
|
25
|
+
url === BROADCAST_PATH || url.endsWith(BROADCAST_PATH)
|
|
26
|
+
if (!isBroadcast || req.method !== 'POST') {
|
|
27
|
+
return next()
|
|
28
|
+
}
|
|
29
|
+
let body = ''
|
|
30
|
+
req.on('data', (chunk) => {
|
|
31
|
+
body += chunk.toString()
|
|
32
|
+
})
|
|
33
|
+
req.on('end', () => {
|
|
34
|
+
try {
|
|
35
|
+
const data = JSON.parse(body || '{}')
|
|
36
|
+
server.ws.send({ type: 'custom', event: RENAME_EVENT, data })
|
|
37
|
+
res.statusCode = 204
|
|
38
|
+
res.end()
|
|
39
|
+
} catch (error) {
|
|
40
|
+
res.statusCode = 400
|
|
41
|
+
res.end(
|
|
42
|
+
error instanceof Error ? error.message : 'Bad rename payload',
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* VitePress 插件 - 根据 configId 查询笔记信息
|
|
5
5
|
*/
|
|
6
|
-
import type { PluginOption } from 'vite'
|
|
7
6
|
import { NoteIndexCache } from '../../core'
|
|
8
|
-
import { logger } from '../../utils'
|
|
7
|
+
import { logger } from '../../utils'
|
|
8
|
+
|
|
9
|
+
import type { PluginOption } from 'vite'
|
|
9
10
|
|
|
10
11
|
export function getNoteByConfigIdPlugin(): PluginOption {
|
|
11
12
|
return {
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Vite 插件 - 处理笔记重命名请求
|
|
5
5
|
*/
|
|
6
|
-
import type { PluginOption } from 'vite'
|
|
7
6
|
import { RenameNoteCommand } from '../../commands/note/RenameNoteCommand'
|
|
8
7
|
|
|
8
|
+
import type { PluginOption } from 'vite'
|
|
9
|
+
|
|
9
10
|
export function renameNotePlugin(): PluginOption {
|
|
10
11
|
const renameCommand = new RenameNoteCommand()
|
|
11
12
|
|
|
@@ -36,6 +37,11 @@ export function renameNotePlugin(): PluginOption {
|
|
|
36
37
|
await renameCommand.renameNote({ noteIndex, newTitle })
|
|
37
38
|
const duration = Date.now() - startTime
|
|
38
39
|
|
|
40
|
+
const newFolderName = `${noteIndex}. ${newTitle.trim()}`
|
|
41
|
+
const newUrl = `/notes/${encodeURIComponent(
|
|
42
|
+
newFolderName,
|
|
43
|
+
)}/README`
|
|
44
|
+
|
|
39
45
|
res.statusCode = 200
|
|
40
46
|
res.setHeader('Content-Type', 'application/json')
|
|
41
47
|
res.end(
|
|
@@ -43,6 +49,8 @@ export function renameNotePlugin(): PluginOption {
|
|
|
43
49
|
success: true,
|
|
44
50
|
duration,
|
|
45
51
|
newTitle,
|
|
52
|
+
newFolderName,
|
|
53
|
+
newUrl,
|
|
46
54
|
message: '重命名完成',
|
|
47
55
|
})
|
|
48
56
|
)
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* VitePress 插件 - 处理笔记配置更新请求
|
|
5
5
|
*/
|
|
6
|
+
import { UpdateNoteConfigCommand } from '../../commands/note/UpdateNoteConfigCommand'
|
|
7
|
+
|
|
6
8
|
import type { PluginOption } from 'vite'
|
|
7
|
-
import { UpdateNoteConfigCommand } from '../../commands/note/UpdateNoteConfigCommand'
|
|
8
9
|
|
|
9
10
|
export function updateConfigPlugin(): PluginOption {
|
|
10
11
|
let updateCommand: UpdateNoteConfigCommand
|
package/vitepress/theme/index.ts
CHANGED
|
@@ -12,20 +12,23 @@
|
|
|
12
12
|
* v2 - https://vitepress.dev/zh/guide/custom-theme
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import type { Theme, EnhanceAppContext } from 'vitepress'
|
|
16
15
|
import DefaultTheme from 'vitepress/theme'
|
|
16
|
+
|
|
17
17
|
import BilibiliOutsidePlayer from '../components/BilibiliOutsidePlayer/BilibiliOutsidePlayer.vue'
|
|
18
18
|
import Discussions from '../components/Discussions/Discussions.vue'
|
|
19
19
|
import EnWordList from '../components/EnWordList/EnWordList.vue'
|
|
20
20
|
import Footprints from '../components/Footprints/Footprints.vue'
|
|
21
|
+
import { useRenameOverlay } from '../components/Layout/composables/useRenameOverlay'
|
|
22
|
+
import { redirectAfterRename } from '../components/Layout/composables/useRenameRedirect'
|
|
21
23
|
import Layout from '../components/Layout/Layout.vue'
|
|
22
|
-
import LoadingPage from '../components/LoadingPage/LoadingPage.vue'
|
|
23
24
|
import MarkMap from '../components/MarkMap/MarkMap.vue'
|
|
24
25
|
import Mermaid from '../components/Mermaid/Mermaid.vue'
|
|
25
26
|
import NotesTable from '../components/NotesTable/NotesTable.vue'
|
|
26
27
|
import Settings from '../components/Settings/Settings.vue'
|
|
27
28
|
import SidebarCard from '../components/SidebarCard/SidebarCard.vue'
|
|
28
29
|
import Tooltip from '../components/Tooltip/Tooltip.vue'
|
|
30
|
+
|
|
31
|
+
import type { Theme, EnhanceAppContext } from 'vitepress'
|
|
29
32
|
import './styles/index.scss'
|
|
30
33
|
|
|
31
34
|
/**
|
|
@@ -40,7 +43,6 @@ function registerCoreComponents(ctx: EnhanceAppContext) {
|
|
|
40
43
|
app.component('E', EnWordList)
|
|
41
44
|
app.component('Footprints', Footprints)
|
|
42
45
|
app.component('F', Footprints)
|
|
43
|
-
app.component('LoadingPage', LoadingPage)
|
|
44
46
|
app.component('Settings', Settings)
|
|
45
47
|
app.component('S', Settings)
|
|
46
48
|
app.component('SidebarCard', SidebarCard)
|
|
@@ -51,6 +53,44 @@ function registerCoreComponents(ctx: EnhanceAppContext) {
|
|
|
51
53
|
app.component('Tooltip', Tooltip)
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
/**
|
|
57
|
+
* 在 dev server 中监听文件夹直接重命名事件,
|
|
58
|
+
* 当当前页面路径属于被重命名的文件夹时,自动跳转到新 URL。
|
|
59
|
+
*/
|
|
60
|
+
function registerRenameHmrListener() {
|
|
61
|
+
if (typeof window === 'undefined') return
|
|
62
|
+
if (typeof import.meta.hot === 'undefined' || !import.meta.hot) return
|
|
63
|
+
|
|
64
|
+
const overlay = useRenameOverlay()
|
|
65
|
+
let handling = false
|
|
66
|
+
|
|
67
|
+
import.meta.hot.on(
|
|
68
|
+
'tnotes:note-renamed',
|
|
69
|
+
async (payload: {
|
|
70
|
+
oldFolder?: string
|
|
71
|
+
newFolder?: string
|
|
72
|
+
noteIndex?: string
|
|
73
|
+
}) => {
|
|
74
|
+
if (handling) return
|
|
75
|
+
if (!payload?.oldFolder || !payload?.newFolder) return
|
|
76
|
+
|
|
77
|
+
const oldSegment = encodeURIComponent(payload.oldFolder)
|
|
78
|
+
if (!window.location.pathname.includes(oldSegment)) return
|
|
79
|
+
|
|
80
|
+
handling = true
|
|
81
|
+
overlay.show({ message: '检测到文件夹重命名', tip: '正在跳转到新地址...' })
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
await redirectAfterRename(
|
|
85
|
+
`notes/${encodeURIComponent(payload.newFolder)}/README`,
|
|
86
|
+
)
|
|
87
|
+
} finally {
|
|
88
|
+
handling = false
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
54
94
|
/**
|
|
55
95
|
* 覆盖选项
|
|
56
96
|
*/
|
|
@@ -78,6 +118,7 @@ export function defineNotesTheme(overrides: NotesThemeOverrides = {}): Theme {
|
|
|
78
118
|
Layout: overrides.Layout ?? Layout,
|
|
79
119
|
enhanceApp(ctx) {
|
|
80
120
|
registerCoreComponents(ctx)
|
|
121
|
+
registerRenameHmrListener()
|
|
81
122
|
overrides.enhanceApp?.(ctx)
|
|
82
123
|
},
|
|
83
124
|
}
|
|
@@ -91,5 +132,6 @@ export default {
|
|
|
91
132
|
Layout,
|
|
92
133
|
enhanceApp(ctx: EnhanceAppContext) {
|
|
93
134
|
registerCoreComponents(ctx)
|
|
135
|
+
registerRenameHmrListener()
|
|
94
136
|
},
|
|
95
137
|
} satisfies Theme
|