1
1
import type { DesignSystem } from '@tailwindcss/language-service/src/util/v4'
2
2
3
3
import postcss from 'postcss'
4
+ import * as fs from 'node:fs/promises'
4
5
import * as path from 'node:path'
5
- import { resolveCssImports } from '../../css'
6
+ import { resolveCssFrom , resolveCssImports } from '../../css'
6
7
import { resolveFrom } from '../resolveFrom'
7
8
import { pathToFileURL } from 'tailwindcss-language-server/src/utils'
8
9
@@ -25,29 +26,40 @@ export async function isMaybeV4(css: string): Promise<boolean> {
25
26
* Create a loader function that can load plugins and config files relative to
26
27
* the CSS file that uses them. However, we don't want missing files to prevent
27
28
* everything from working so we'll let the error handler decide how to proceed.
28
- *
29
- * @param {object } param0
30
- * @returns
31
29
*/
32
30
function createLoader < T > ( {
31
+ legacy,
33
32
filepath,
34
33
onError,
35
34
} : {
35
+ legacy : boolean
36
36
filepath : string
37
- onError : ( id : string , error : unknown ) => T
37
+ onError : ( id : string , error : unknown , resourceType : string ) => T
38
38
} ) {
39
- let baseDir = path . dirname ( filepath )
40
39
let cacheKey = `${ + Date . now ( ) } `
41
40
42
- return async function loadFile ( id : string ) {
41
+ async function loadFile ( id : string , base : string , resourceType : string ) {
43
42
try {
44
- let resolved = resolveFrom ( baseDir , id )
43
+ let resolved = resolveFrom ( base , id )
44
+
45
45
let url = pathToFileURL ( resolved )
46
46
url . searchParams . append ( 't' , cacheKey )
47
47
48
48
return await import ( url . href ) . then ( ( m ) => m . default ?? m )
49
49
} catch ( err ) {
50
- return onError ( id , err )
50
+ return onError ( id , err , resourceType )
51
+ }
52
+ }
53
+
54
+ if ( legacy ) {
55
+ let baseDir = path . dirname ( filepath )
56
+ return ( id : string ) => loadFile ( id , baseDir , 'module' )
57
+ }
58
+
59
+ return async ( id : string , base : string , resourceType : string ) => {
60
+ return {
61
+ base,
62
+ module : await loadFile ( id , base , resourceType ) ,
51
63
}
52
64
}
53
65
}
@@ -65,14 +77,53 @@ export async function loadDesignSystem(
65
77
return null
66
78
}
67
79
80
+ let supportsImports = false
81
+ try {
82
+ await tailwindcss . __unstable__loadDesignSystem ( css , {
83
+ loadStylesheet : async ( id : string , base : string ) => {
84
+ supportsImports = true
85
+ return { base, content : '' }
86
+ } ,
87
+ } )
88
+ } catch { }
89
+
68
90
// Step 2: Use postcss to resolve `@import` rules in the CSS file
69
- // TODO: What if someone is actively editing their config and introduces a syntax error?
70
- // We don't want to necessarily throw away the knowledge that we have a v4 project.
71
- let resolved = await resolveCssImports ( ) . process ( css , { from : filepath } )
91
+ if ( ! supportsImports ) {
92
+ let resolved = await resolveCssImports ( ) . process ( css , { from : filepath } )
93
+ css = resolved . css
94
+ }
72
95
73
96
// Step 3: Take the resolved CSS and pass it to v4's `loadDesignSystem`
74
- let design : DesignSystem = await tailwindcss . __unstable__loadDesignSystem ( resolved . css , {
97
+ let design : DesignSystem = await tailwindcss . __unstable__loadDesignSystem ( css , {
98
+ base : path . dirname ( filepath ) ,
99
+
100
+ // v4.0.0-alpha.25+
101
+ loadModule : createLoader ( {
102
+ legacy : false ,
103
+ filepath,
104
+ onError : ( id , err , resourceType ) => {
105
+ console . error ( `Unable to load ${ resourceType } : ${ id } ` , err )
106
+
107
+ if ( resourceType === 'config' ) {
108
+ return { }
109
+ } else if ( resourceType === 'plugin' ) {
110
+ return ( ) => { }
111
+ }
112
+ } ,
113
+ } ) ,
114
+
115
+ loadStylesheet : async ( id : string , base : string ) => {
116
+ let resolved = resolveCssFrom ( base , id )
117
+
118
+ return {
119
+ base : path . dirname ( resolved ) ,
120
+ content : await fs . readFile ( resolved , 'utf-8' ) ,
121
+ }
122
+ } ,
123
+
124
+ // v4.0.0-alpha.24 and below
75
125
loadPlugin : createLoader ( {
126
+ legacy : true ,
76
127
filepath,
77
128
onError ( id , err ) {
78
129
console . error ( `Unable to load plugin: ${ id } ` , err )
@@ -82,6 +133,7 @@ export async function loadDesignSystem(
82
133
} ) ,
83
134
84
135
loadConfig : createLoader ( {
136
+ legacy : true ,
85
137
filepath,
86
138
onError ( id , err ) {
87
139
console . error ( `Unable to load config: ${ id } ` , err )
0 commit comments