@@ -77,15 +77,31 @@ export async function findClassNamesInRange(
77
77
includeCustom : boolean = true
78
78
) : Promise < DocumentClassName [ ] > {
79
79
const classLists = await findClassListsInRange ( state , doc , range , mode , includeCustom )
80
- return flatten ( classLists . map ( getClassNamesInClassList ) )
80
+ return flatten (
81
+ classLists . flatMap ( ( classList ) => {
82
+ if ( Array . isArray ( classList ) ) {
83
+ return classList . map ( getClassNamesInClassList )
84
+ } else {
85
+ return [ getClassNamesInClassList ( classList ) ]
86
+ }
87
+ } )
88
+ )
81
89
}
82
90
83
91
export async function findClassNamesInDocument (
84
92
state : State ,
85
93
doc : TextDocument
86
94
) : Promise < DocumentClassName [ ] > {
87
95
const classLists = await findClassListsInDocument ( state , doc )
88
- return flatten ( classLists . map ( getClassNamesInClassList ) )
96
+ return flatten (
97
+ classLists . flatMap ( ( classList ) => {
98
+ if ( Array . isArray ( classList ) ) {
99
+ return classList . map ( getClassNamesInClassList )
100
+ } else {
101
+ return [ getClassNamesInClassList ( classList ) ]
102
+ }
103
+ } )
104
+ )
89
105
}
90
106
91
107
export function findClassListsInCssRange ( doc : TextDocument , range ?: Range ) : DocumentClassList [ ] {
@@ -182,15 +198,15 @@ export async function findClassListsInHtmlRange(
182
198
state : State ,
183
199
doc : TextDocument ,
184
200
range ?: Range
185
- ) : Promise < DocumentClassList [ ] > {
201
+ ) : Promise < Array < DocumentClassList | DocumentClassList [ ] > > {
186
202
const text = doc . getText ( range )
187
203
188
204
const matches = matchClassAttributes (
189
205
text ,
190
206
( await state . editor . getConfiguration ( doc . uri ) ) . tailwindCSS . classAttributes
191
207
)
192
208
193
- const result : DocumentClassList [ ] = [ ]
209
+ const result : Array < DocumentClassList | DocumentClassList [ ] > = [ ]
194
210
195
211
matches . forEach ( ( match ) => {
196
212
const subtext = text . substr ( match . index + match [ 0 ] . length - 1 )
@@ -201,9 +217,11 @@ export async function findClassListsInHtmlRange(
201
217
: getClassAttributeLexer ( )
202
218
lexer . reset ( subtext )
203
219
204
- let classLists : { value : string ; offset : number } [ ] = [ ]
205
- let token : moo . Token
220
+ let classLists : Array < { value : string ; offset : number } | { value : string ; offset : number } [ ] > =
221
+ [ ]
222
+ let rootClassList : { value : string ; offset : number } [ ] = [ ]
206
223
let currentClassList : { value : string ; offset : number }
224
+ let depth = 0
207
225
208
226
try {
209
227
for ( let token of lexer ) {
@@ -218,56 +236,53 @@ export async function findClassListsInHtmlRange(
218
236
}
219
237
} else {
220
238
if ( currentClassList ) {
221
- classLists . push ( {
222
- value : currentClassList . value ,
223
- offset : currentClassList . offset ,
224
- } )
239
+ if ( depth === 0 ) {
240
+ rootClassList . push ( {
241
+ value : currentClassList . value ,
242
+ offset : currentClassList . offset ,
243
+ } )
244
+ } else {
245
+ classLists . push ( {
246
+ value : currentClassList . value ,
247
+ offset : currentClassList . offset ,
248
+ } )
249
+ }
225
250
}
226
251
currentClassList = undefined
227
252
}
253
+ if ( token . type === 'lbrace' ) {
254
+ depth += 1
255
+ } else if ( token . type === 'rbrace' ) {
256
+ depth -= 1
257
+ }
228
258
}
229
259
} catch ( _ ) { }
230
260
231
261
if ( currentClassList ) {
232
- classLists . push ( {
233
- value : currentClassList . value ,
234
- offset : currentClassList . offset ,
235
- } )
262
+ if ( depth === 0 ) {
263
+ rootClassList . push ( {
264
+ value : currentClassList . value ,
265
+ offset : currentClassList . offset ,
266
+ } )
267
+ } else {
268
+ classLists . push ( {
269
+ value : currentClassList . value ,
270
+ offset : currentClassList . offset ,
271
+ } )
272
+ }
236
273
}
237
274
275
+ classLists . push ( rootClassList )
276
+
238
277
result . push (
239
278
...classLists
240
- . map ( ( { value, offset } ) => {
241
- if ( value . trim ( ) === '' ) {
242
- return null
243
- }
244
-
245
- const before = value . match ( / ^ \s * / )
246
- const beforeOffset = before === null ? 0 : before [ 0 ] . length
247
- const after = value . match ( / \s * $ / )
248
- const afterOffset = after === null ? 0 : - after [ 0 ] . length
249
-
250
- const start = indexToPosition (
251
- text ,
252
- match . index + match [ 0 ] . length - 1 + offset + beforeOffset
253
- )
254
- const end = indexToPosition (
255
- text ,
256
- match . index + match [ 0 ] . length - 1 + offset + value . length + afterOffset
257
- )
258
-
259
- return {
260
- classList : value . substr ( beforeOffset , value . length + afterOffset ) ,
261
- range : {
262
- start : {
263
- line : ( range ?. start . line || 0 ) + start . line ,
264
- character : ( end . line === 0 ? range ?. start . character || 0 : 0 ) + start . character ,
265
- } ,
266
- end : {
267
- line : ( range ?. start . line || 0 ) + end . line ,
268
- character : ( end . line === 0 ? range ?. start . character || 0 : 0 ) + end . character ,
269
- } ,
270
- } ,
279
+ . map ( ( classList ) => {
280
+ if ( Array . isArray ( classList ) ) {
281
+ return classList
282
+ . map ( ( classList ) => resolveClassList ( classList , text , match , range ) )
283
+ . filter ( ( x ) => x !== null )
284
+ } else {
285
+ return resolveClassList ( classList , text , match , range )
271
286
}
272
287
} )
273
288
. filter ( ( x ) => x !== null )
@@ -277,14 +292,51 @@ export async function findClassListsInHtmlRange(
277
292
return result
278
293
}
279
294
295
+ function resolveClassList (
296
+ classList : { value : string ; offset : number } ,
297
+ text : string ,
298
+ match : RegExpMatchArray ,
299
+ range ?: Range
300
+ ) : DocumentClassList {
301
+ let { value, offset } = classList
302
+ if ( value . trim ( ) === '' ) {
303
+ return null
304
+ }
305
+
306
+ const before = value . match ( / ^ \s * / )
307
+ const beforeOffset = before === null ? 0 : before [ 0 ] . length
308
+ const after = value . match ( / \s * $ / )
309
+ const afterOffset = after === null ? 0 : - after [ 0 ] . length
310
+
311
+ const start = indexToPosition ( text , match . index + match [ 0 ] . length - 1 + offset + beforeOffset )
312
+ const end = indexToPosition (
313
+ text ,
314
+ match . index + match [ 0 ] . length - 1 + offset + value . length + afterOffset
315
+ )
316
+
317
+ return {
318
+ classList : value . substr ( beforeOffset , value . length + afterOffset ) ,
319
+ range : {
320
+ start : {
321
+ line : ( range ?. start . line || 0 ) + start . line ,
322
+ character : ( end . line === 0 ? range ?. start . character || 0 : 0 ) + start . character ,
323
+ } ,
324
+ end : {
325
+ line : ( range ?. start . line || 0 ) + end . line ,
326
+ character : ( end . line === 0 ? range ?. start . character || 0 : 0 ) + end . character ,
327
+ } ,
328
+ } ,
329
+ }
330
+ }
331
+
280
332
export async function findClassListsInRange (
281
333
state : State ,
282
334
doc : TextDocument ,
283
335
range ?: Range ,
284
336
mode ?: 'html' | 'css' ,
285
337
includeCustom : boolean = true
286
- ) : Promise < DocumentClassList [ ] > {
287
- let classLists : DocumentClassList [ ]
338
+ ) : Promise < Array < DocumentClassList | DocumentClassList [ ] > > {
339
+ let classLists : Array < DocumentClassList | DocumentClassList [ ] >
288
340
if ( mode === 'css' ) {
289
341
classLists = findClassListsInCssRange ( doc , range )
290
342
} else {
@@ -296,7 +348,7 @@ export async function findClassListsInRange(
296
348
export async function findClassListsInDocument (
297
349
state : State ,
298
350
doc : TextDocument
299
- ) : Promise < DocumentClassList [ ] > {
351
+ ) : Promise < Array < DocumentClassList | DocumentClassList [ ] > > {
300
352
if ( isCssDoc ( state , doc ) ) {
301
353
return findClassListsInCssRange ( doc )
302
354
}
0 commit comments