11import type { RuleContext } from '../types.js' ;
22import fs from 'fs' ;
33import path from 'path' ;
4- import { getPackageJson } from './get-package-json.js' ;
4+ import { getPackageJsons } from './get-package-json.js' ;
55import { getFilename , getSourceCode } from './compat.js' ;
66
77const isRunInBrowser = ! fs . readFileSync ;
88
9- export type SvelteContext = {
10- svelteVersion : '3/4' | '5' | 'undetermined' ;
11- svelteFileType : '.svelte' | '.svelte.[js|ts]' | null ;
12- runes : boolean | 'undetermined' ;
13- svelteKitVersion : '1-next' | '1' | '2' | null ;
9+ export type SvelteContext = (
10+ | ( {
11+ svelteVersion : '3/4' ;
12+ } & {
13+ svelteFileType : '.svelte' | 'other' ;
14+ runes : null ;
15+ } )
16+ | ( {
17+ svelteVersion : '5' ;
18+ } & (
19+ | {
20+ svelteFileType : '.svelte' | '.svelte.[js|ts]' ;
21+ /** If a user uses a parser other than `svelte-eslint-parser`, `undetermined` will be set. */
22+ runes : boolean | 'undetermined' ;
23+ }
24+ | {
25+ /** e.g. `foo.js` / `package.json` */
26+ svelteFileType : 'other' ;
27+ runes : null ;
28+ }
29+ ) )
30+ | {
31+ /** For projects that do not use Svelte. */
32+ svelteVersion : null ;
33+ svelteFileType : null ;
34+ runes : null ;
35+ }
36+ ) & {
37+ svelteKitVersion : '1.0.0-next' | '1' | '2' | null ;
1438 svelteKitFileType :
1539 | '+page.svelte'
1640 | '+page.js'
@@ -23,7 +47,7 @@ export type SvelteContext = {
2347 | null ;
2448} ;
2549
26- function getSvelteFileType ( filePath : string ) : SvelteContext [ 'svelteFileType' ] | null {
50+ function getSvelteFileType ( filePath : string ) : NonNullable < SvelteContext [ 'svelteFileType' ] > {
2751 if ( filePath . endsWith ( '.svelte' ) ) {
2852 return '.svelte' ;
2953 }
@@ -32,7 +56,7 @@ function getSvelteFileType(filePath: string): SvelteContext['svelteFileType'] |
3256 return '.svelte.[js|ts]' ;
3357 }
3458
35- return null ;
59+ return 'other' ;
3660}
3761
3862function getSvelteKitFileTypeFromFilePath ( filePath : string ) : SvelteContext [ 'svelteKitFileType' ] {
@@ -112,6 +136,29 @@ function getSvelteKitContext(
112136 } ;
113137}
114138
139+ function getSvelteVersion ( filePath : string ) : SvelteContext [ 'svelteVersion' ] {
140+ // Hack: if it runs in browser, it regards as Svelte project.
141+ if ( isRunInBrowser ) return '5' ;
142+ try {
143+ const packageJsons = getPackageJsons ( filePath ) ;
144+ for ( const packageJson of packageJsons ) {
145+ const version = packageJson . dependencies ?. svelte ?? packageJson . devDependencies ?. svelte ;
146+ if ( typeof version !== 'string' ) {
147+ continue ;
148+ }
149+ const major = version . split ( '.' ) [ 0 ] ;
150+ if ( major === '3' || major === '4' ) {
151+ return '3/4' ;
152+ }
153+ return major as SvelteContext [ 'svelteVersion' ] ;
154+ }
155+ } catch {
156+ /** do nothing */
157+ }
158+
159+ return null ;
160+ }
161+
115162/**
116163 * Check givin file is under SvelteKit project.
117164 *
@@ -124,41 +171,28 @@ function getSvelteKitVersion(filePath: string): SvelteContext['svelteKitVersion'
124171 // Hack: if it runs in browser, it regards as SvelteKit project.
125172 if ( isRunInBrowser ) return '2' ;
126173 try {
127- const packageJson = getPackageJson ( filePath ) ;
128- if ( ! packageJson ) return null ;
129- if ( packageJson . name === 'eslint-plugin-svelte' )
174+ const packageJsons = getPackageJsons ( filePath ) ;
175+ if ( packageJsons . length === 0 ) return null ;
176+ if ( packageJsons [ 0 ] . name === 'eslint-plugin-svelte' ) {
130177 // Hack: CI removes `@sveltejs/kit` and it returns false and test failed.
131- // So always it returns true if it runs on the package.
178+ // So always it returns 2 if it runs on the package.
132179 return '2' ;
133-
134- const version =
135- packageJson . dependencies ?. [ '@sveltejs/kit' ] ?? packageJson . devDependencies ?. [ '@sveltejs/kit' ] ;
136- if ( typeof version !== 'string' ) {
137- return null ;
138180 }
139- if ( version . startsWith ( '1.0.0-next.' ) ) {
140- return '1-next' ;
141- } else if ( version . startsWith ( '1.' ) ) {
142- return '1' ;
143- } else if ( version . startsWith ( '2.' ) ) {
144- return '2' ;
181+
182+ for ( const packageJson of packageJsons ) {
183+ const version =
184+ packageJson . dependencies ?. [ '@sveltejs/kit' ] ??
185+ packageJson . devDependencies ?. [ '@sveltejs/kit' ] ;
186+ if ( typeof version !== 'string' ) {
187+ return null ;
188+ }
189+ return version . split ( '.' ) [ 0 ] as SvelteContext [ 'svelteKitVersion' ] ;
145190 }
146- // If unknown version, it recognize as v2.
147- return '2' ;
148191 } catch {
149- return null ;
192+ /** do nothing */
150193 }
151- }
152194
153- function getSvelteVersion ( compilerVersion : string | undefined ) : SvelteContext [ 'svelteVersion' ] {
154- if ( compilerVersion == null ) {
155- return 'undetermined' ;
156- }
157- const version = parseInt ( compilerVersion . split ( '.' ) [ 0 ] , 10 ) ;
158- if ( version === 3 || version === 4 ) {
159- return '3/4' ;
160- }
161- return String ( version ) as '5' ;
195+ return null ;
162196}
163197
164198/**
@@ -168,22 +202,57 @@ function getSvelteVersion(compilerVersion: string | undefined): SvelteContext['s
168202 */
169203function getProjectRootDir ( filePath : string ) : string | null {
170204 if ( isRunInBrowser ) return null ;
171- const packageJsonFilePath = getPackageJson ( filePath ) ?. filePath ;
205+ const packageJsons = getPackageJsons ( filePath ) ;
206+ if ( packageJsons . length === 0 ) {
207+ return null ;
208+ }
209+ const packageJsonFilePath = packageJsons [ 0 ] . filePath ;
172210 if ( ! packageJsonFilePath ) return null ;
173211 return path . dirname ( path . resolve ( packageJsonFilePath ) ) ;
174212}
175213
176214export function getSvelteContext ( context : RuleContext ) : SvelteContext | null {
177215 const { parserServices } = getSourceCode ( context ) ;
178216 const { svelteParseContext } = parserServices ;
179- const compilerVersion = svelteParseContext ?. compilerVersion ;
180217 const filePath = getFilename ( context ) ;
181218 const svelteKitContext = getSvelteKitContext ( context ) ;
219+ const svelteVersion = getSvelteVersion ( filePath ) ;
220+ const svelteFileType = getSvelteFileType ( filePath ) ;
221+
222+ if ( svelteVersion == null ) {
223+ return {
224+ svelteVersion : null ,
225+ svelteFileType : null ,
226+ runes : null ,
227+ svelteKitVersion : svelteKitContext . svelteKitVersion ,
228+ svelteKitFileType : svelteKitContext . svelteKitFileType
229+ } ;
230+ }
231+
232+ if ( svelteFileType === 'other' ) {
233+ return {
234+ svelteVersion,
235+ svelteFileType,
236+ runes : null ,
237+ svelteKitVersion : svelteKitContext . svelteKitVersion ,
238+ svelteKitFileType : svelteKitContext . svelteKitFileType
239+ } ;
240+ }
241+
242+ if ( svelteVersion === '3/4' ) {
243+ return {
244+ svelteVersion,
245+ svelteFileType : svelteFileType === '.svelte' ? '.svelte' : 'other' ,
246+ runes : null ,
247+ svelteKitVersion : svelteKitContext . svelteKitVersion ,
248+ svelteKitFileType : svelteKitContext . svelteKitFileType
249+ } ;
250+ }
182251
183252 return {
184- svelteVersion : getSvelteVersion ( compilerVersion ) ,
253+ svelteVersion,
185254 runes : svelteParseContext ?. runes ?? 'undetermined' ,
186- svelteFileType : getSvelteFileType ( filePath ) ,
255+ svelteFileType,
187256 svelteKitVersion : svelteKitContext . svelteKitVersion ,
188257 svelteKitFileType : svelteKitContext . svelteKitFileType
189258 } ;
0 commit comments