@tnotesjs/core 0.0.8 → 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.
@@ -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,7 +3,7 @@
3
3
  *
4
4
  * Vite 插件 - 处理笔记重命名请求
5
5
  */
6
- import { RenameNoteCommand } from '../../commands/note/RenameNoteCommand'
6
+ import { RenameNoteCommand } from '../../commands/note/RenameNoteCommand'
7
7
 
8
8
  import type { PluginOption } from 'vite'
9
9
 
@@ -37,6 +37,11 @@ export function renameNotePlugin(): PluginOption {
37
37
  await renameCommand.renameNote({ noteIndex, newTitle })
38
38
  const duration = Date.now() - startTime
39
39
 
40
+ const newFolderName = `${noteIndex}. ${newTitle.trim()}`
41
+ const newUrl = `/notes/${encodeURIComponent(
42
+ newFolderName,
43
+ )}/README`
44
+
40
45
  res.statusCode = 200
41
46
  res.setHeader('Content-Type', 'application/json')
42
47
  res.end(
@@ -44,6 +49,8 @@ export function renameNotePlugin(): PluginOption {
44
49
  success: true,
45
50
  duration,
46
51
  newTitle,
52
+ newFolderName,
53
+ newUrl,
47
54
  message: '重命名完成',
48
55
  })
49
56
  )
@@ -12,20 +12,21 @@
12
12
  * v2 - https://vitepress.dev/zh/guide/custom-theme
13
13
  */
14
14
 
15
- import DefaultTheme from 'vitepress/theme'
15
+ import DefaultTheme from 'vitepress/theme'
16
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
- import Tooltip from '../components/Tooltip/Tooltip.vue'
29
+ import Tooltip from '../components/Tooltip/Tooltip.vue'
29
30
 
30
31
  import type { Theme, EnhanceAppContext } from 'vitepress'
31
32
  import './styles/index.scss'
@@ -42,7 +43,6 @@ function registerCoreComponents(ctx: EnhanceAppContext) {
42
43
  app.component('E', EnWordList)
43
44
  app.component('Footprints', Footprints)
44
45
  app.component('F', Footprints)
45
- app.component('LoadingPage', LoadingPage)
46
46
  app.component('Settings', Settings)
47
47
  app.component('S', Settings)
48
48
  app.component('SidebarCard', SidebarCard)
@@ -53,6 +53,44 @@ function registerCoreComponents(ctx: EnhanceAppContext) {
53
53
  app.component('Tooltip', Tooltip)
54
54
  }
55
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
+
56
94
  /**
57
95
  * 覆盖选项
58
96
  */
@@ -80,6 +118,7 @@ export function defineNotesTheme(overrides: NotesThemeOverrides = {}): Theme {
80
118
  Layout: overrides.Layout ?? Layout,
81
119
  enhanceApp(ctx) {
82
120
  registerCoreComponents(ctx)
121
+ registerRenameHmrListener()
83
122
  overrides.enhanceApp?.(ctx)
84
123
  },
85
124
  }
@@ -93,5 +132,6 @@ export default {
93
132
  Layout,
94
133
  enhanceApp(ctx: EnhanceAppContext) {
95
134
  registerCoreComponents(ctx)
135
+ registerRenameHmrListener()
96
136
  },
97
137
  } satisfies Theme