@tnotesjs/core 0.1.27 → 0.2.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/README.md +2 -1
- package/package.json +3 -1
- package/templates/sub-repo/.gitattributes +30 -0
- package/templates/sub-repo/.github/workflows/deploy.yml +87 -0
- package/templates/sub-repo/.vitepress/config.mts +12 -0
- package/templates/sub-repo/.vitepress/env.d.ts +10 -0
- package/templates/sub-repo/.vitepress/theme/index.ts +12 -0
- package/templates/sub-repo/.vscode/settings.json +330 -0
- package/templates/sub-repo/.vscode/tnotes.code-snippets +110 -0
- package/templates/sub-repo/public/favicon.ico +0 -0
- package/templates/sub-repo/public/logo.png +0 -0
- package/templates/sub-repo/tsconfig.json +45 -0
- package/vitepress/assets/icons/icon__setting_dark.svg +4 -0
- package/vitepress/assets/icons/icon__setting_light.svg +4 -0
- package/vitepress/assets/icons/index.ts +2 -2
- package/vitepress/client/localSearchIndexBridge.ts +24 -0
- package/vitepress/components/Discussions/Discussions.vue +1 -1
- package/vitepress/components/Footprints/Footprints.vue +90 -25
- package/vitepress/components/Layout/CustomSidebar.vue +489 -117
- package/vitepress/components/Layout/Layout.vue +5 -0
- package/vitepress/components/Layout/NavBarSettingsTrigger.vue +10 -2
- package/vitepress/components/Layout/SidebarItems.vue +517 -342
- package/vitepress/components/Layout/SidebarNavBefore.vue +1 -50
- package/vitepress/components/Layout/SidebarResizeHandle.vue +6 -23
- package/vitepress/components/Layout/composables/docLayoutLogic.ts +59 -0
- package/vitepress/components/Layout/composables/useDocLayout.test.ts +69 -0
- package/vitepress/components/Layout/composables/useDocLayout.ts +128 -0
- package/vitepress/components/Layout/composables/useSidebarDrag.ts +514 -0
- package/vitepress/components/Layout/composables/useSidebarLayout.ts +25 -8
- package/vitepress/components/Layout/composables/useVSCodeIntegration.ts +8 -3
- package/vitepress/components/Layout/sidebarCollapsedState.test.ts +183 -0
- package/vitepress/components/Layout/sidebarCollapsedState.ts +241 -0
- package/vitepress/components/Layout/sidebarDragLogic.test.ts +1146 -0
- package/vitepress/components/Layout/sidebarDragLogic.ts +1307 -0
- package/vitepress/components/Layout/sidebarHitTest.test.ts +572 -0
- package/vitepress/components/Layout/sidebarHitTest.ts +801 -0
- package/vitepress/components/Layout/sidebarItemRenderLogic.test.ts +53 -0
- package/vitepress/components/Layout/sidebarItemRenderLogic.ts +50 -0
- package/vitepress/components/MarkMap/MarkMap.vue +67 -10
- package/vitepress/components/Settings/Settings.vue +78 -74
- package/vitepress/components/SidebarCard/FolderTreeItems.vue +268 -0
- package/vitepress/components/SidebarCard/SidebarCard.vue +125 -274
- package/vitepress/components/constants.ts +18 -6
- package/vitepress/components/sidebar.data.ts +13 -11
- package/vitepress/components/sidebarTreeHelpers.test.ts +142 -0
- package/vitepress/components/sidebarTreeHelpers.ts +168 -0
- package/vitepress/components/utils/vscodePaths.test.ts +41 -0
- package/vitepress/components/utils/vscodePaths.ts +52 -0
- package/vitepress/config/index.ts +2 -0
- package/vitepress/plugins/localSearchIndexBuilder.ts +209 -0
- package/vitepress/plugins/localSearchReindex.test.ts +46 -0
- package/vitepress/plugins/localSearchReindexLogic.ts +50 -0
- package/vitepress/plugins/localSearchReindexPatch.test.ts +30 -0
- package/vitepress/plugins/localSearchReindexPatch.ts +37 -0
- package/vitepress/plugins/localSearchReindexPlugin.ts +318 -0
- package/vitepress/plugins/sidebarStructurePlugin.ts +209 -63
- package/vitepress/theme/index.ts +8 -0
- package/vitepress/theme/styles/base.scss +0 -8
- package/vitepress/theme/styles/components/markmap.scss +23 -2
- package/vitepress/theme/styles/components/swiper.scss +1 -1
- package/vitepress/theme/styles/doc-layout.scss +212 -0
- package/vitepress/theme/styles/index.scss +3 -0
- package/vitepress/theme/styles/layout.scss +60 -10
- package/dist/chunk-4KG6RXFS.js +0 -4637
- package/dist/chunk-AGSL3VZE.js +0 -193
- package/dist/cli/index.js +0 -683
- package/dist/index.js +0 -8
- package/dist/vitepress/config/index.js +0 -1178
- package/vitepress/assets/icons/icon__mindmap.svg +0 -1
- package/vitepress/assets/icons/icon__setting.svg +0 -1
- package/vitepress/components/SidebarCard/MindMapView.vue +0 -488
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
* VitePress dev middleware - 处理语雀风格侧边栏的目录结构操作。
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { scheduleNoteSearchReindex } from './localSearchReindexPlugin'
|
|
8
|
+
import { FileWatcherService, NoteService, TocService } from '../../services'
|
|
9
|
+
|
|
8
10
|
|
|
9
11
|
import type { NoteInfo } from '../../types'
|
|
10
12
|
import type { IncomingMessage, ServerResponse } from 'http'
|
|
@@ -15,6 +17,7 @@ interface JsonResponse {
|
|
|
15
17
|
message?: string
|
|
16
18
|
sidebarChanged?: boolean
|
|
17
19
|
redirectUrl?: string
|
|
20
|
+
redirectNoteIndex?: string | null
|
|
18
21
|
createdNotes?: Array<{ index: string; dirName: string; link: string }>
|
|
19
22
|
deletedNoteIndexes?: string[]
|
|
20
23
|
}
|
|
@@ -47,14 +50,6 @@ function normalizePathname(url?: string): string {
|
|
|
47
50
|
return (url || '').split('?')[0]
|
|
48
51
|
}
|
|
49
52
|
|
|
50
|
-
function normalizeGroupPath(value: unknown): string[] {
|
|
51
|
-
if (!Array.isArray(value) || value.length === 0) {
|
|
52
|
-
throw new Error('Missing groupPath')
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return value.map((item) => String(item))
|
|
56
|
-
}
|
|
57
|
-
|
|
58
53
|
function normalizeCount(value: unknown): number {
|
|
59
54
|
const count = Number(value ?? 1)
|
|
60
55
|
if (!Number.isInteger(count) || count < 1 || count > 100) {
|
|
@@ -71,6 +66,22 @@ function getCreatedNotePayload(notes: NoteInfo[]) {
|
|
|
71
66
|
}))
|
|
72
67
|
}
|
|
73
68
|
|
|
69
|
+
function buildNoteReadmeLink(note: NoteInfo): string {
|
|
70
|
+
return `/notes/${encodeURIComponent(note.dirName)}/README`
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function resolveDeleteRedirectUrl(
|
|
74
|
+
noteService: NoteService,
|
|
75
|
+
previousNoteIndex: string | null,
|
|
76
|
+
): string {
|
|
77
|
+
if (!previousNoteIndex) return '/'
|
|
78
|
+
|
|
79
|
+
const previousNote = noteService.getNoteByIndex(previousNoteIndex)
|
|
80
|
+
if (!previousNote) return '/'
|
|
81
|
+
|
|
82
|
+
return buildNoteReadmeLink(previousNote)
|
|
83
|
+
}
|
|
84
|
+
|
|
74
85
|
async function withSuspendedWatcher<T>(task: () => Promise<T>): Promise<T> {
|
|
75
86
|
const watcher = FileWatcherService.getInstance()
|
|
76
87
|
|
|
@@ -84,7 +95,7 @@ async function withSuspendedWatcher<T>(task: () => Promise<T>): Promise<T> {
|
|
|
84
95
|
|
|
85
96
|
export function sidebarStructurePlugin(): PluginOption {
|
|
86
97
|
const noteService = NoteService.getInstance()
|
|
87
|
-
const
|
|
98
|
+
const tocService = TocService.getInstance()
|
|
88
99
|
|
|
89
100
|
async function createNotes(count: number) {
|
|
90
101
|
const notes = []
|
|
@@ -112,17 +123,22 @@ export function sidebarStructurePlugin(): PluginOption {
|
|
|
112
123
|
return notes
|
|
113
124
|
}
|
|
114
125
|
|
|
126
|
+
async function refreshTocAndSidebar() {
|
|
127
|
+
await tocService.regenerateSidebar()
|
|
128
|
+
}
|
|
129
|
+
|
|
115
130
|
return {
|
|
116
131
|
name: 'tnotes-sidebar-structure',
|
|
117
132
|
configureServer(server) {
|
|
118
133
|
server.middlewares.use(async (req, res, next) => {
|
|
119
134
|
const pathname = normalizePathname(req.url)
|
|
120
135
|
const handledPaths = new Set([
|
|
121
|
-
'/__tnotes_sidebar_rename_group',
|
|
122
|
-
'/__tnotes_sidebar_delete_group',
|
|
123
136
|
'/__tnotes_sidebar_create_note',
|
|
124
137
|
'/__tnotes_sidebar_create_notes',
|
|
138
|
+
'/__tnotes_sidebar_create_folder',
|
|
125
139
|
'/__tnotes_sidebar_delete_note',
|
|
140
|
+
'/__tnotes_sidebar_delete_entry',
|
|
141
|
+
'/__tnotes_sidebar_rename_folder',
|
|
126
142
|
'/__tnotes_sidebar_reorder',
|
|
127
143
|
])
|
|
128
144
|
|
|
@@ -140,81 +156,165 @@ export function sidebarStructurePlugin(): PluginOption {
|
|
|
140
156
|
const data = await readJsonBody(req)
|
|
141
157
|
|
|
142
158
|
const result = await withSuspendedWatcher(async () => {
|
|
143
|
-
if (pathname === '/
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
159
|
+
if (pathname === '/__tnotes_sidebar_delete_note') {
|
|
160
|
+
const noteIndex = String(data.noteIndex || '')
|
|
161
|
+
if (!noteIndex) throw new Error('Missing noteIndex')
|
|
162
|
+
|
|
163
|
+
const previousNoteIndex =
|
|
164
|
+
await tocService.getPreviousNoteIndexBeforeDelete(noteIndex)
|
|
165
|
+
|
|
166
|
+
await tocService.deleteNoteFromToc(noteIndex)
|
|
167
|
+
await noteService.deleteNote(noteIndex)
|
|
168
|
+
await refreshTocAndSidebar()
|
|
169
|
+
scheduleNoteSearchReindex('api:delete-note')
|
|
170
|
+
|
|
148
171
|
return {
|
|
149
172
|
success: true,
|
|
150
173
|
sidebarChanged: true,
|
|
151
|
-
|
|
174
|
+
redirectUrl: resolveDeleteRedirectUrl(
|
|
175
|
+
noteService,
|
|
176
|
+
previousNoteIndex,
|
|
177
|
+
),
|
|
178
|
+
redirectNoteIndex: previousNoteIndex,
|
|
179
|
+
deletedNoteIndexes: [noteIndex],
|
|
180
|
+
message: '笔记已删除',
|
|
152
181
|
}
|
|
153
182
|
}
|
|
154
183
|
|
|
155
|
-
if (pathname === '/
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
for (const noteIndex of noteIndexes) {
|
|
162
|
-
await noteService.deleteNote(noteIndex)
|
|
184
|
+
if (pathname === '/__tnotes_sidebar_delete_entry') {
|
|
185
|
+
const tocLineIndex = Number(data.tocLineIndex)
|
|
186
|
+
if (!Number.isInteger(tocLineIndex) || tocLineIndex < 0) {
|
|
187
|
+
throw new Error('Missing tocLineIndex')
|
|
163
188
|
}
|
|
164
189
|
|
|
165
|
-
|
|
190
|
+
const currentNoteIndex = String(data.currentNoteIndex || '')
|
|
191
|
+
const previousNoteIndex =
|
|
192
|
+
await tocService.getPreviousNoteIndexBeforeEntryDelete(
|
|
193
|
+
tocLineIndex,
|
|
194
|
+
)
|
|
195
|
+
const inSubtree =
|
|
196
|
+
currentNoteIndex &&
|
|
197
|
+
(await tocService.isNoteInTocEntrySubtree(
|
|
198
|
+
tocLineIndex,
|
|
199
|
+
currentNoteIndex,
|
|
200
|
+
))
|
|
201
|
+
|
|
202
|
+
const deletedNoteIndexes =
|
|
203
|
+
await tocService.deleteTocEntryCascade(tocLineIndex)
|
|
204
|
+
await refreshTocAndSidebar()
|
|
205
|
+
scheduleNoteSearchReindex('api:delete-entry')
|
|
206
|
+
|
|
166
207
|
return {
|
|
167
208
|
success: true,
|
|
168
209
|
sidebarChanged: true,
|
|
169
|
-
redirectUrl:
|
|
170
|
-
|
|
171
|
-
|
|
210
|
+
redirectUrl: inSubtree
|
|
211
|
+
? resolveDeleteRedirectUrl(noteService, previousNoteIndex)
|
|
212
|
+
: undefined,
|
|
213
|
+
redirectNoteIndex: inSubtree ? previousNoteIndex : null,
|
|
214
|
+
deletedNoteIndexes,
|
|
215
|
+
message: '已删除',
|
|
172
216
|
}
|
|
173
217
|
}
|
|
174
218
|
|
|
175
|
-
if (pathname === '/
|
|
176
|
-
const
|
|
177
|
-
|
|
219
|
+
if (pathname === '/__tnotes_sidebar_rename_folder') {
|
|
220
|
+
const tocLineIndex = Number(data.tocLineIndex)
|
|
221
|
+
const newTitle = String(data.newTitle || '')
|
|
222
|
+
if (!Number.isInteger(tocLineIndex) || tocLineIndex < 0) {
|
|
223
|
+
throw new Error('Missing tocLineIndex')
|
|
224
|
+
}
|
|
178
225
|
|
|
179
|
-
await
|
|
180
|
-
await
|
|
181
|
-
await readmeService.refreshHomeReadmeAndSidebar()
|
|
226
|
+
await tocService.renameFolderInToc(tocLineIndex, newTitle)
|
|
227
|
+
await refreshTocAndSidebar()
|
|
182
228
|
|
|
183
229
|
return {
|
|
184
230
|
success: true,
|
|
185
231
|
sidebarChanged: true,
|
|
186
|
-
|
|
187
|
-
deletedNoteIndexes: [noteIndex],
|
|
188
|
-
message: '笔记已删除',
|
|
232
|
+
message: '目录已重命名',
|
|
189
233
|
}
|
|
190
234
|
}
|
|
191
235
|
|
|
192
236
|
if (pathname === '/__tnotes_sidebar_reorder') {
|
|
193
|
-
if (
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
237
|
+
if (
|
|
238
|
+
data.node_uuid &&
|
|
239
|
+
data.action === 'prependChild' &&
|
|
240
|
+
!data.target_uuid
|
|
241
|
+
) {
|
|
242
|
+
await tocService.prependToRootByNodeId(String(data.node_uuid))
|
|
243
|
+
await refreshTocAndSidebar()
|
|
244
|
+
return {
|
|
245
|
+
success: true,
|
|
246
|
+
sidebarChanged: true,
|
|
247
|
+
message: '排序已更新',
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (
|
|
252
|
+
data.node_uuid &&
|
|
253
|
+
data.target_uuid &&
|
|
254
|
+
(data.action === 'moveAfter' || data.action === 'prependChild')
|
|
255
|
+
) {
|
|
256
|
+
if (data.action === 'moveAfter') {
|
|
257
|
+
await tocService.moveAfterByNodeId(
|
|
258
|
+
String(data.node_uuid),
|
|
259
|
+
String(data.target_uuid),
|
|
260
|
+
)
|
|
201
261
|
} else {
|
|
202
|
-
await
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
262
|
+
await tocService.prependChildByNodeId(
|
|
263
|
+
String(data.node_uuid),
|
|
264
|
+
String(data.target_uuid),
|
|
265
|
+
)
|
|
206
266
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
267
|
+
await refreshTocAndSidebar()
|
|
268
|
+
return {
|
|
269
|
+
success: true,
|
|
270
|
+
sidebarChanged: true,
|
|
271
|
+
message: '排序已更新',
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const dragTocLineIndex = Number(data.dragTocLineIndex)
|
|
276
|
+
if (!Number.isInteger(dragTocLineIndex) || dragTocLineIndex < 0) {
|
|
277
|
+
throw new Error('Missing dragTocLineIndex')
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const placement =
|
|
281
|
+
data.targetType === 'group' || data.placement === 'inside'
|
|
282
|
+
? 'inside'
|
|
283
|
+
: data.placement === 'after'
|
|
284
|
+
? 'after'
|
|
285
|
+
: 'before'
|
|
286
|
+
|
|
287
|
+
if (
|
|
288
|
+
data.targetTocLineIndex !== undefined &&
|
|
289
|
+
data.targetTocLineIndex !== null
|
|
290
|
+
) {
|
|
291
|
+
await tocService.moveTocEntryByLineIndex(dragTocLineIndex, {
|
|
292
|
+
targetTocLineIndex: Number(data.targetTocLineIndex),
|
|
293
|
+
placement,
|
|
294
|
+
})
|
|
295
|
+
} else if (
|
|
296
|
+
Array.isArray(data.targetFolderPath) &&
|
|
297
|
+
data.targetFolderPath.length > 0
|
|
298
|
+
) {
|
|
299
|
+
await tocService.moveTocEntryByLineIndex(dragTocLineIndex, {
|
|
300
|
+
targetType: 'folder',
|
|
301
|
+
targetFolderPath: data.targetFolderPath.map(String),
|
|
302
|
+
placement,
|
|
303
|
+
})
|
|
213
304
|
} else {
|
|
214
|
-
|
|
305
|
+
const targetNoteIndex = String(
|
|
306
|
+
data.targetNoteIndex || data.targetGroupNoteIndex || '',
|
|
307
|
+
)
|
|
308
|
+
if (!targetNoteIndex) throw new Error('Missing targetNoteIndex')
|
|
309
|
+
|
|
310
|
+
await tocService.moveTocEntryByLineIndex(dragTocLineIndex, {
|
|
311
|
+
targetType: 'note',
|
|
312
|
+
targetNoteIndex,
|
|
313
|
+
placement,
|
|
314
|
+
})
|
|
215
315
|
}
|
|
216
316
|
|
|
217
|
-
await
|
|
317
|
+
await refreshTocAndSidebar()
|
|
218
318
|
return {
|
|
219
319
|
success: true,
|
|
220
320
|
sidebarChanged: true,
|
|
@@ -222,22 +322,68 @@ export function sidebarStructurePlugin(): PluginOption {
|
|
|
222
322
|
}
|
|
223
323
|
}
|
|
224
324
|
|
|
325
|
+
if (pathname === '/__tnotes_sidebar_create_folder') {
|
|
326
|
+
const parentTocLineIndex = Number(data.parentTocLineIndex)
|
|
327
|
+
const title = String(data.title || '')
|
|
328
|
+
if (
|
|
329
|
+
!Number.isInteger(parentTocLineIndex) ||
|
|
330
|
+
parentTocLineIndex < 0
|
|
331
|
+
) {
|
|
332
|
+
throw new Error('Missing parentTocLineIndex')
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
await tocService.insertFolderUnderParent(
|
|
336
|
+
parentTocLineIndex,
|
|
337
|
+
title,
|
|
338
|
+
)
|
|
339
|
+
await refreshTocAndSidebar()
|
|
340
|
+
|
|
341
|
+
return {
|
|
342
|
+
success: true,
|
|
343
|
+
sidebarChanged: true,
|
|
344
|
+
message: '目录已创建',
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
225
348
|
const count = normalizeCount(data.count)
|
|
226
349
|
const notes = await createNotes(count)
|
|
227
350
|
|
|
228
351
|
if (data.targetNoteIndex) {
|
|
229
352
|
const placement = data.placement === 'after' ? 'after' : 'before'
|
|
230
|
-
await
|
|
353
|
+
await tocService.insertNotesAroundNote(
|
|
231
354
|
String(data.targetNoteIndex),
|
|
232
355
|
notes,
|
|
233
356
|
placement,
|
|
234
357
|
)
|
|
358
|
+
} else if (
|
|
359
|
+
data.parentTocLineIndex !== undefined &&
|
|
360
|
+
data.parentTocLineIndex !== null
|
|
361
|
+
) {
|
|
362
|
+
await tocService.insertNotesUnderTocLine(
|
|
363
|
+
Number(data.parentTocLineIndex),
|
|
364
|
+
notes,
|
|
365
|
+
)
|
|
366
|
+
} else if (
|
|
367
|
+
Array.isArray(data.parentFolderPath) &&
|
|
368
|
+
data.parentFolderPath.length > 0
|
|
369
|
+
) {
|
|
370
|
+
await tocService.insertNotesUnderFolder(
|
|
371
|
+
data.parentFolderPath.map(String),
|
|
372
|
+
notes,
|
|
373
|
+
)
|
|
374
|
+
} else if (data.parentNoteIndex) {
|
|
375
|
+
await tocService.insertNotesUnderParent(
|
|
376
|
+
String(data.parentNoteIndex),
|
|
377
|
+
notes,
|
|
378
|
+
)
|
|
235
379
|
} else {
|
|
236
|
-
const
|
|
237
|
-
|
|
380
|
+
for (const note of notes) {
|
|
381
|
+
await tocService.appendNoteToToc(note.index)
|
|
382
|
+
}
|
|
238
383
|
}
|
|
239
384
|
|
|
240
|
-
await
|
|
385
|
+
await refreshTocAndSidebar()
|
|
386
|
+
scheduleNoteSearchReindex('api:create-notes')
|
|
241
387
|
|
|
242
388
|
return {
|
|
243
389
|
success: true,
|
package/vitepress/theme/index.ts
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import DefaultTheme from 'vitepress/theme'
|
|
16
16
|
|
|
17
|
+
import { initTnotesSearchIndexHmr } from '../client/localSearchIndexBridge'
|
|
17
18
|
import BilibiliOutsidePlayer from '../components/BilibiliOutsidePlayer/BilibiliOutsidePlayer.vue'
|
|
18
19
|
import Discussions from '../components/Discussions/Discussions.vue'
|
|
19
20
|
import EnWordList from '../components/EnWordList/EnWordList.vue'
|
|
@@ -27,6 +28,7 @@ import NotesTable from '../components/NotesTable/NotesTable.vue'
|
|
|
27
28
|
import SidebarCard from '../components/SidebarCard/SidebarCard.vue'
|
|
28
29
|
import Tooltip from '../components/Tooltip/Tooltip.vue'
|
|
29
30
|
|
|
31
|
+
|
|
30
32
|
import type { Theme, EnhanceAppContext } from 'vitepress'
|
|
31
33
|
import './styles/index.scss'
|
|
32
34
|
|
|
@@ -88,6 +90,10 @@ function registerRenameHmrListener() {
|
|
|
88
90
|
)
|
|
89
91
|
}
|
|
90
92
|
|
|
93
|
+
function registerSearchIndexHmrListener() {
|
|
94
|
+
initTnotesSearchIndexHmr()
|
|
95
|
+
}
|
|
96
|
+
|
|
91
97
|
/**
|
|
92
98
|
* 覆盖选项
|
|
93
99
|
*/
|
|
@@ -116,6 +122,7 @@ export function defineNotesTheme(overrides: NotesThemeOverrides = {}): Theme {
|
|
|
116
122
|
enhanceApp(ctx) {
|
|
117
123
|
registerCoreComponents(ctx)
|
|
118
124
|
registerRenameHmrListener()
|
|
125
|
+
registerSearchIndexHmrListener()
|
|
119
126
|
overrides.enhanceApp?.(ctx)
|
|
120
127
|
},
|
|
121
128
|
}
|
|
@@ -130,5 +137,6 @@ export default {
|
|
|
130
137
|
enhanceApp(ctx: EnhanceAppContext) {
|
|
131
138
|
registerCoreComponents(ctx)
|
|
132
139
|
registerRenameHmrListener()
|
|
140
|
+
registerSearchIndexHmrListener()
|
|
133
141
|
},
|
|
134
142
|
} satisfies Theme
|
|
@@ -16,8 +16,9 @@
|
|
|
16
16
|
border-radius: 6px;
|
|
17
17
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
|
|
18
18
|
backdrop-filter: blur(8px);
|
|
19
|
-
opacity:
|
|
20
|
-
pointer-events:
|
|
19
|
+
opacity: 1;
|
|
20
|
+
pointer-events: auto;
|
|
21
|
+
z-index: 10;
|
|
21
22
|
transition: opacity 0.3s ease;
|
|
22
23
|
color: var(--vp-c-tip-1);
|
|
23
24
|
font-weight: 700;
|
|
@@ -73,6 +74,26 @@
|
|
|
73
74
|
background-color: rgba(255, 255, 255, 0.1);
|
|
74
75
|
}
|
|
75
76
|
|
|
77
|
+
html.markmap-dark .markmapContainer,
|
|
78
|
+
.markmapContainer.is-markmap-dark {
|
|
79
|
+
background-color: #1d1d1d;
|
|
80
|
+
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
html.markmap-dark .markmapContainer:hover,
|
|
84
|
+
.markmapContainer.is-markmap-dark:hover {
|
|
85
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
html.markmap-dark .markmapContainer:fullscreen,
|
|
89
|
+
html.markmap-dark .markmapContainer:-ms-fullscreen,
|
|
90
|
+
html.markmap-dark .markmapContainer:-webkit-full-screen,
|
|
91
|
+
.markmapContainer.is-markmap-dark:fullscreen,
|
|
92
|
+
.markmapContainer.is-markmap-dark:-ms-fullscreen,
|
|
93
|
+
.markmapContainer.is-markmap-dark:-webkit-full-screen {
|
|
94
|
+
background: #1d1d1d;
|
|
95
|
+
}
|
|
96
|
+
|
|
76
97
|
/* #endregion */
|
|
77
98
|
|
|
78
99
|
/* ===================================== */
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 文档三栏布局(语雀式)
|
|
3
|
+
* - 左目录 / 右正文目录贴齐视口左右两侧
|
|
4
|
+
* - 中间正文:超宽 / 标准 750px
|
|
5
|
+
* - 视口不足时 aside-auto-hidden / sidebar-auto-hidden
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
:root {
|
|
9
|
+
--tn-aside-width: 300px;
|
|
10
|
+
--tn-content-standard-width: 750px;
|
|
11
|
+
--tn-content-min-width: 640px;
|
|
12
|
+
--tn-doc-layout-padding: 16px;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* 取消 VitePress 1440px 居中壳:顶栏与正文区贴齐左目录、右目录 */
|
|
16
|
+
@media (min-width: 960px) {
|
|
17
|
+
.VPNavBar.has-sidebar .container {
|
|
18
|
+
max-width: 100% !important;
|
|
19
|
+
margin: 0 !important;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* 站点标题固定在视口左上方,宽度与左目录一致 */
|
|
23
|
+
.VPNavBar.has-sidebar .title {
|
|
24
|
+
left: 0 !important;
|
|
25
|
+
padding-left: var(--tn-sidebar-inset-x, 8px) !important;
|
|
26
|
+
padding-right: var(--tn-sidebar-inset-x, 8px) !important;
|
|
27
|
+
width: var(--vp-sidebar-width) !important;
|
|
28
|
+
box-sizing: border-box;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.VPNavBar.has-sidebar .divider {
|
|
32
|
+
padding-left: var(--vp-sidebar-width) !important;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.VPNavBar.has-sidebar .content {
|
|
36
|
+
padding-left: var(--vp-sidebar-width) !important;
|
|
37
|
+
padding-right: var(--tn-sidebar-inset-x, 8px) !important;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.VPContent.has-sidebar {
|
|
41
|
+
padding-left: var(--vp-sidebar-width) !important;
|
|
42
|
+
padding-right: 0 !important;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@media (min-width: 1440px) {
|
|
47
|
+
.VPNavBar.has-sidebar .title {
|
|
48
|
+
padding-left: var(--tn-sidebar-inset-x, 8px) !important;
|
|
49
|
+
width: var(--vp-sidebar-width) !important;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.VPNavBar.has-sidebar .divider {
|
|
53
|
+
padding-left: var(--vp-sidebar-width) !important;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.VPNavBar.has-sidebar .content {
|
|
57
|
+
padding-left: var(--vp-sidebar-width) !important;
|
|
58
|
+
padding-right: var(--tn-sidebar-inset-x, 8px) !important;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.VPContent.has-sidebar {
|
|
62
|
+
padding-left: var(--vp-sidebar-width) !important;
|
|
63
|
+
padding-right: 0 !important;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* 有右栏时为正文区预留 300px,右栏 fixed 贴视口右侧 */
|
|
68
|
+
@media (min-width: 1280px) {
|
|
69
|
+
html:not(.aside-auto-hidden):not(.content-fullscreen)
|
|
70
|
+
.VPContent.has-sidebar:has(.VPDoc.has-aside) {
|
|
71
|
+
padding-right: var(--tn-aside-width) !important;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.VPDoc.has-aside .aside {
|
|
75
|
+
position: fixed !important;
|
|
76
|
+
top: var(--vp-nav-height) !important;
|
|
77
|
+
right: 0 !important;
|
|
78
|
+
left: auto !important;
|
|
79
|
+
bottom: 0 !important;
|
|
80
|
+
z-index: 10;
|
|
81
|
+
order: 0 !important;
|
|
82
|
+
flex: none !important;
|
|
83
|
+
width: var(--tn-aside-width) !important;
|
|
84
|
+
max-width: var(--tn-aside-width) !important;
|
|
85
|
+
padding: 0 var(--tn-sidebar-inset-x, 8px) !important;
|
|
86
|
+
box-sizing: border-box;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.VPDoc .aside-container {
|
|
90
|
+
position: relative !important;
|
|
91
|
+
top: auto !important;
|
|
92
|
+
width: 100% !important;
|
|
93
|
+
height: 100% !important;
|
|
94
|
+
padding-top: 48px !important;
|
|
95
|
+
overflow-x: hidden;
|
|
96
|
+
overflow-y: auto;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.VPDoc .aside-curtain {
|
|
100
|
+
width: 100% !important;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* aside 已 fixed,container 不再为右栏预留 flex 列 */
|
|
104
|
+
.VPDoc.has-aside .container {
|
|
105
|
+
display: block !important;
|
|
106
|
+
max-width: none !important;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.VPDoc.has-aside .content {
|
|
110
|
+
width: 100% !important;
|
|
111
|
+
max-width: none !important;
|
|
112
|
+
min-width: 0 !important;
|
|
113
|
+
margin: 0 !important;
|
|
114
|
+
padding: 48px var(--tn-sidebar-inset-x, 8px) 128px !important;
|
|
115
|
+
box-sizing: border-box;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* 正文页宽模式 */
|
|
120
|
+
html.content-width-wide .VPDoc.has-aside .content-container {
|
|
121
|
+
max-width: none !important;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
html.content-width-standard .VPDoc.has-aside .content-container {
|
|
125
|
+
max-width: var(--tn-content-standard-width) !important;
|
|
126
|
+
margin-inline: auto !important;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
html.content-width-standard .VPDoc:not(.has-aside) .content-container {
|
|
130
|
+
max-width: var(--tn-content-standard-width) !important;
|
|
131
|
+
margin-inline: auto !important;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* 视口不足:先隐藏右侧正文目录 */
|
|
135
|
+
html.aside-auto-hidden .VPDoc .aside {
|
|
136
|
+
display: none !important;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
html.aside-auto-hidden .VPDoc.has-aside .content {
|
|
140
|
+
max-width: none !important;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
html.aside-auto-hidden .VPContent.has-sidebar {
|
|
144
|
+
padding-right: 0 !important;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* 视口仍不足:自动折叠左目录(仅桌面;移动端由 VitePress 抽屉侧栏负责) */
|
|
148
|
+
@media (min-width: 960px) {
|
|
149
|
+
html.sidebar-auto-hidden .VPSidebar {
|
|
150
|
+
padding-left: 0 !important;
|
|
151
|
+
padding-right: 0 !important;
|
|
152
|
+
overflow: hidden;
|
|
153
|
+
transform: translateX(-100%);
|
|
154
|
+
pointer-events: none;
|
|
155
|
+
transition: transform 0.25s ease, opacity 0.25s ease;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
html.sidebar-auto-hidden .VPNavBar.has-sidebar .VPNavBarTitle {
|
|
159
|
+
display: none !important;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
html.sidebar-auto-hidden .VPNavBar.has-sidebar {
|
|
163
|
+
background-color: var(--vp-nav-bg-color) !important;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
html.sidebar-auto-hidden .VPNavBar.has-sidebar .divider {
|
|
167
|
+
padding-left: 0 !important;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
html.sidebar-auto-hidden .VPNavBar.has-sidebar .content {
|
|
171
|
+
padding-left: 0 !important;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
html.sidebar-auto-hidden .VPContent.has-sidebar {
|
|
175
|
+
margin-left: 0 !important;
|
|
176
|
+
padding-left: 0 !important;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* 全屏内容模式:隐藏右栏,正文横向铺满视口(覆盖标准/超宽页宽) */
|
|
181
|
+
html.content-fullscreen {
|
|
182
|
+
.VPDoc .aside {
|
|
183
|
+
display: none !important;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.VPContent.has-sidebar {
|
|
187
|
+
padding-left: 0 !important;
|
|
188
|
+
padding-right: 0 !important;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.VPDoc.has-aside .container,
|
|
192
|
+
.VPDoc .container {
|
|
193
|
+
max-width: none !important;
|
|
194
|
+
width: 100% !important;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.VPDoc.has-aside .content,
|
|
198
|
+
.VPDoc .content {
|
|
199
|
+
max-width: none !important;
|
|
200
|
+
width: 100% !important;
|
|
201
|
+
margin: 0 !important;
|
|
202
|
+
padding: 48px var(--tn-sidebar-inset-x, 8px) 128px !important;
|
|
203
|
+
box-sizing: border-box;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
&.content-width-standard .VPDoc .content-container,
|
|
207
|
+
&.content-width-wide .VPDoc .content-container {
|
|
208
|
+
max-width: none !important;
|
|
209
|
+
width: 100% !important;
|
|
210
|
+
margin-inline: 0 !important;
|
|
211
|
+
}
|
|
212
|
+
}
|