1
1
import { TextDocument , Range , Position } from 'vscode-languageserver'
2
2
import { DocumentClassName , DocumentClassList , State } from './state'
3
3
import lineColumn from 'line-column'
4
- import { isCssContext } from './css'
5
- import { isHtmlContext } from './html'
4
+ import { isCssContext , isCssDoc } from './css'
5
+ import { isHtmlContext , isHtmlDoc , isSvelteDoc , isVueDoc } from './html'
6
6
import { isWithinRange } from './isWithinRange'
7
- import { isJsContext } from './js'
7
+ import { isJsContext , isJsDoc } from './js'
8
8
import { getClassAttributeLexer } from './lexers'
9
9
10
10
export function findAll ( re : RegExp , str : string ) : RegExpMatchArray [ ] {
@@ -26,8 +26,8 @@ export function findLast(re: RegExp, str: string): RegExpMatchArray {
26
26
27
27
export function findClassNamesInRange (
28
28
doc : TextDocument ,
29
- range : Range ,
30
- mode : 'html' | 'css'
29
+ range ? : Range ,
30
+ mode ? : 'html' | 'css'
31
31
) : DocumentClassName [ ] {
32
32
const classLists = findClassListsInRange ( doc , range , mode )
33
33
return [ ] . concat . apply (
@@ -66,10 +66,11 @@ export function findClassNamesInRange(
66
66
67
67
export function findClassListsInCssRange (
68
68
doc : TextDocument ,
69
- range : Range
69
+ range ? : Range
70
70
) : DocumentClassList [ ] {
71
71
const text = doc . getText ( range )
72
72
const matches = findAll ( / ( @ a p p l y \s + ) (?< classList > [ ^ ; } ] + ) [ ; } ] / g, text )
73
+ const globalStart : Position = range ? range . start : { line : 0 , character : 0 }
73
74
74
75
return matches . map ( ( match ) => {
75
76
const start = indexToPosition ( text , match . index + match [ 1 ] . length )
@@ -81,12 +82,14 @@ export function findClassListsInCssRange(
81
82
classList : match . groups . classList ,
82
83
range : {
83
84
start : {
84
- line : range . start . line + start . line ,
85
- character : range . start . character + start . character ,
85
+ line : globalStart . line + start . line ,
86
+ character :
87
+ ( end . line === 0 ? globalStart . character : 0 ) + start . character ,
86
88
} ,
87
89
end : {
88
- line : range . start . line + end . line ,
89
- character : range . start . character + end . character ,
90
+ line : globalStart . line + end . line ,
91
+ character :
92
+ ( end . line === 0 ? globalStart . character : 0 ) + end . character ,
90
93
} ,
91
94
} ,
92
95
}
@@ -172,11 +175,14 @@ export function findClassListsInHtmlRange(
172
175
range : {
173
176
start : {
174
177
line : range . start . line + start . line ,
175
- character : range . start . character + start . character ,
178
+ character :
179
+ ( end . line === 0 ? range . start . character : 0 ) +
180
+ start . character ,
176
181
} ,
177
182
end : {
178
183
line : range . start . line + end . line ,
179
- character : range . start . character + end . character ,
184
+ character :
185
+ ( end . line === 0 ? range . start . character : 0 ) + end . character ,
180
186
} ,
181
187
} ,
182
188
}
@@ -199,6 +205,80 @@ export function findClassListsInRange(
199
205
return findClassListsInHtmlRange ( doc , range )
200
206
}
201
207
208
+ export function findClassListsInDocument (
209
+ state : State ,
210
+ doc : TextDocument
211
+ ) : DocumentClassList [ ] {
212
+ if ( isCssDoc ( state , doc ) ) {
213
+ return findClassListsInCssRange ( doc )
214
+ }
215
+
216
+ if ( isVueDoc ( doc ) ) {
217
+ let text = doc . getText ( )
218
+ let blocks = findAll (
219
+ / < (?< type > t e m p l a t e | s t y l e | s c r i p t ) \b [ ^ > ] * > .* ?( < \/ \k<type > > | $ ) / gis,
220
+ text
221
+ )
222
+ let htmlRanges : Range [ ] = [ ]
223
+ let cssRanges : Range [ ] = [ ]
224
+ for ( let i = 0 ; i < blocks . length ; i ++ ) {
225
+ let range = {
226
+ start : indexToPosition ( text , blocks [ i ] . index ) ,
227
+ end : indexToPosition ( text , blocks [ i ] . index + blocks [ i ] [ 0 ] . length ) ,
228
+ }
229
+ if ( blocks [ i ] . groups . type === 'style' ) {
230
+ cssRanges . push ( range )
231
+ } else {
232
+ htmlRanges . push ( range )
233
+ }
234
+ }
235
+ return [ ] . concat . apply (
236
+ [ ] ,
237
+ [
238
+ ...htmlRanges . map ( ( range ) => findClassListsInHtmlRange ( doc , range ) ) ,
239
+ ...cssRanges . map ( ( range ) => findClassListsInCssRange ( doc , range ) ) ,
240
+ ]
241
+ )
242
+ }
243
+
244
+ if ( isHtmlDoc ( state , doc ) || isJsDoc ( state , doc ) || isSvelteDoc ( doc ) ) {
245
+ let text = doc . getText ( )
246
+ let styleBlocks = findAll ( / < s t y l e (?: \s [ ^ > ] * > | > ) .* ?( < \/ s t y l e > | $ ) / gis, text )
247
+ let htmlRanges : Range [ ] = [ ]
248
+ let cssRanges : Range [ ] = [ ]
249
+ let currentIndex = 0
250
+
251
+ for ( let i = 0 ; i < styleBlocks . length ; i ++ ) {
252
+ htmlRanges . push ( {
253
+ start : indexToPosition ( text , currentIndex ) ,
254
+ end : indexToPosition ( text , styleBlocks [ i ] . index ) ,
255
+ } )
256
+ cssRanges . push ( {
257
+ start : indexToPosition ( text , styleBlocks [ i ] . index ) ,
258
+ end : indexToPosition (
259
+ text ,
260
+ styleBlocks [ i ] . index + styleBlocks [ i ] [ 0 ] . length
261
+ ) ,
262
+ } )
263
+ currentIndex = styleBlocks [ i ] . index + styleBlocks [ i ] [ 0 ] . length
264
+ }
265
+ htmlRanges . push ( {
266
+ start : indexToPosition ( text , currentIndex ) ,
267
+ end : indexToPosition ( text , text . length ) ,
268
+ } )
269
+
270
+ return [ ] . concat . apply (
271
+ [ ] ,
272
+ [
273
+ ...htmlRanges . map ( ( range ) => findClassListsInHtmlRange ( doc , range ) ) ,
274
+ ...cssRanges . map ( ( range ) => findClassListsInCssRange ( doc , range ) ) ,
275
+ ]
276
+ )
277
+ }
278
+
279
+ return [ ]
280
+ }
281
+
202
282
function indexToPosition ( str : string , index : number ) : Position {
203
283
const { line, col } = lineColumn ( str + '\n' , index )
204
284
return { line : line - 1 , character : col - 1 }
0 commit comments