@@ -77,15 +77,31 @@ export async function findClassNamesInRange(
7777 includeCustom : boolean = true
7878) : Promise < DocumentClassName [ ] > {
7979 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+ )
8189}
8290
8391export async function findClassNamesInDocument (
8492 state : State ,
8593 doc : TextDocument
8694) : Promise < DocumentClassName [ ] > {
8795 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+ )
89105}
90106
91107export function findClassListsInCssRange ( doc : TextDocument , range ?: Range ) : DocumentClassList [ ] {
@@ -182,15 +198,15 @@ export async function findClassListsInHtmlRange(
182198 state : State ,
183199 doc : TextDocument ,
184200 range ?: Range
185- ) : Promise < DocumentClassList [ ] > {
201+ ) : Promise < Array < DocumentClassList | DocumentClassList [ ] > > {
186202 const text = doc . getText ( range )
187203
188204 const matches = matchClassAttributes (
189205 text ,
190206 ( await state . editor . getConfiguration ( doc . uri ) ) . tailwindCSS . classAttributes
191207 )
192208
193- const result : DocumentClassList [ ] = [ ]
209+ const result : Array < DocumentClassList | DocumentClassList [ ] > = [ ]
194210
195211 matches . forEach ( ( match ) => {
196212 const subtext = text . substr ( match . index + match [ 0 ] . length - 1 )
@@ -201,9 +217,11 @@ export async function findClassListsInHtmlRange(
201217 : getClassAttributeLexer ( )
202218 lexer . reset ( subtext )
203219
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 } [ ] = [ ]
206223 let currentClassList : { value : string ; offset : number }
224+ let depth = 0
207225
208226 try {
209227 for ( let token of lexer ) {
@@ -218,56 +236,53 @@ export async function findClassListsInHtmlRange(
218236 }
219237 } else {
220238 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+ }
225250 }
226251 currentClassList = undefined
227252 }
253+ if ( token . type === 'lbrace' ) {
254+ depth += 1
255+ } else if ( token . type === 'rbrace' ) {
256+ depth -= 1
257+ }
228258 }
229259 } catch ( _ ) { }
230260
231261 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+ }
236273 }
237274
275+ classLists . push ( rootClassList )
276+
238277 result . push (
239278 ...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 )
271286 }
272287 } )
273288 . filter ( ( x ) => x !== null )
@@ -277,14 +292,51 @@ export async function findClassListsInHtmlRange(
277292 return result
278293}
279294
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+
280332export async function findClassListsInRange (
281333 state : State ,
282334 doc : TextDocument ,
283335 range ?: Range ,
284336 mode ?: 'html' | 'css' ,
285337 includeCustom : boolean = true
286- ) : Promise < DocumentClassList [ ] > {
287- let classLists : DocumentClassList [ ]
338+ ) : Promise < Array < DocumentClassList | DocumentClassList [ ] > > {
339+ let classLists : Array < DocumentClassList | DocumentClassList [ ] >
288340 if ( mode === 'css' ) {
289341 classLists = findClassListsInCssRange ( doc , range )
290342 } else {
@@ -296,7 +348,7 @@ export async function findClassListsInRange(
296348export async function findClassListsInDocument (
297349 state : State ,
298350 doc : TextDocument
299- ) : Promise < DocumentClassList [ ] > {
351+ ) : Promise < Array < DocumentClassList | DocumentClassList [ ] > > {
300352 if ( isCssDoc ( state , doc ) ) {
301353 return findClassListsInCssRange ( doc )
302354 }
0 commit comments