@@ -2,13 +2,13 @@ import { existsSync } from 'node:fs'
2
2
import { basename , dirname } from 'node:path'
3
3
import type { LoadedSlidevData } from '@slidev/parser/fs'
4
4
import { load } from '@slidev/parser/fs'
5
- import { computed , markRaw , onScopeDispose , reactive , ref , watchEffect } from '@vue/runtime-core'
6
- import { commands , window , workspace } from 'vscode'
5
+ import { computed , markRaw , onScopeDispose , reactive , ref , watch , watchEffect } from '@vue/runtime-core'
6
+ import { window , workspace } from 'vscode'
7
7
import { slash } from '@antfu/utils'
8
8
import { useLogger } from './views/logger'
9
9
import { findShallowestPath } from './utils/findShallowestPath'
10
10
import { useVscodeContext } from './composables/useVscodeContext'
11
- import { forceEnabled } from './configs'
11
+ import { exclude , forceEnabled , include } from './configs'
12
12
13
13
export interface SlidevProject {
14
14
readonly entry : string
@@ -23,17 +23,21 @@ export const activeProject = computed(() => activeEntry.value ? projects.get(act
23
23
export const activeSlidevData = computed ( ( ) => activeProject . value ?. data )
24
24
export const activeUserRoot = computed ( ( ) => activeProject . value ?. userRoot )
25
25
26
- async function loadExistingProjects ( ) {
27
- const files = await workspace . findFiles ( '**/*.md' , '**/node_modules/**' )
26
+ async function addExistingProjects ( ) {
27
+ const files = new Set < string > ( )
28
+ for ( const glob of include . value ) {
29
+ ( await workspace . findFiles ( glob , exclude . value ) )
30
+ . forEach ( file => files . add ( file . fsPath ) )
31
+ }
28
32
for ( const file of files ) {
29
- const path = slash ( file . fsPath )
30
- if ( basename ( path ) === 'slides.md' )
33
+ const path = slash ( file )
34
+ if ( ! projects . has ( path ) )
31
35
( await addProjectEffect ( path ) ) ( )
32
36
}
33
37
}
34
38
35
39
export async function rescanProjects ( ) {
36
- await loadExistingProjects ( )
40
+ await addExistingProjects ( )
37
41
for ( const project of projects . values ( ) ) {
38
42
if ( ! existsSync ( project . entry ) ) {
39
43
projects . delete ( project . entry )
@@ -48,7 +52,7 @@ export function useProjects() {
48
52
const logger = useLogger ( )
49
53
50
54
async function init ( ) {
51
- await loadExistingProjects ( )
55
+ await addExistingProjects ( )
52
56
await autoSetActiveEntry ( )
53
57
}
54
58
init ( )
@@ -69,55 +73,39 @@ export function useProjects() {
69
73
70
74
let pendingUpdate : { cancelled : boolean } | null = null
71
75
72
- // TODO: Not sure why file creation is not being detected
73
76
const fsWatcher = workspace . createFileSystemWatcher ( '**/*.md' )
77
+ onScopeDispose ( ( ) => fsWatcher . dispose ( ) )
78
+
74
79
fsWatcher . onDidChange ( async ( uri ) => {
75
- const path = slash ( uri . fsPath )
80
+ const path = slash ( uri . fsPath ) . toLowerCase ( )
76
81
logger . info ( `File ${ path } changed.` )
77
82
const startMs = Date . now ( )
78
83
pendingUpdate && ( pendingUpdate . cancelled = true )
79
84
const thisUpdate = pendingUpdate = { cancelled : false }
80
85
const effects : ( ( ) => void ) [ ] = [ ]
81
- let maybeNewEntry = path . endsWith ( '.md' ) && basename ( path ) . toLowerCase ( ) !== 'readme.md'
82
86
for ( const project of projects . values ( ) ) {
83
- if ( project . data . watchFiles . includes ( path ) )
84
- maybeNewEntry = false
85
- else
87
+ if ( ! project . data . watchFiles . some ( f => f . toLowerCase ( ) === path ) )
86
88
continue
87
89
88
90
if ( existsSync ( project . entry ) ) {
89
91
const newData = markRaw ( await load ( project . userRoot , project . entry ) )
90
- maybeNewEntry &&= newData . watchFiles . includes ( path )
91
92
effects . push ( ( ) => {
92
93
project . data = newData
93
94
logger . info ( `Project ${ project . entry } updated.` )
94
95
} )
95
96
}
96
- else {
97
- effects . push ( ( ) => {
98
- projects . delete ( project . entry )
99
- logger . info ( `Project ${ project . entry } removed.` )
100
- if ( activeEntry . value === project . entry ) {
101
- window . showWarningMessage ( 'The active slides file has been deleted. Please choose another one.' , 'Choose another one' )
102
- . then ( result => result && commands . executeCommand ( 'slidev.choose-entry' ) )
103
- }
104
- } )
105
- }
97
+
106
98
if ( thisUpdate . cancelled )
107
99
return
108
100
}
109
101
110
- if ( basename ( path ) . toLocaleLowerCase ( ) === 'slides.md' && ! projects . has ( path ) )
111
- effects . push ( await addProjectEffect ( path ) )
112
-
113
- if ( thisUpdate . cancelled )
114
- return
115
-
116
102
effects . map ( effect => effect ( ) )
117
- autoSetActiveEntry ( )
118
103
logger . info ( `All affected Slidev projects updated in ${ Date . now ( ) - startMs } ms.` )
119
104
} )
120
- onScopeDispose ( ( ) => fsWatcher . dispose ( ) )
105
+ fsWatcher . onDidCreate ( rescanProjects )
106
+ fsWatcher . onDidDelete ( rescanProjects )
107
+
108
+ watch ( include , rescanProjects )
121
109
}
122
110
123
111
export async function addProject ( entry : string ) {
0 commit comments