1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
import { TextDocument, Range, Position } from 'vscode-languageserver'
import { DocumentClassName, DocumentClassList } from './state'
import lineColumn from 'line-column'
export function findAll(re: RegExp, str: string): RegExpMatchArray[] {
let match: RegExpMatchArray
let matches: RegExpMatchArray[] = []
while ((match = re.exec(str)) !== null) {
matches.push({ ...match })
}
return matches
}
export function findLast(re: RegExp, str: string): RegExpMatchArray {
const matches = findAll(re, str)
if (matches.length === 0) {
return null
}
return matches[matches.length - 1]
}
export function findClassNamesInRange(
doc: TextDocument,
range: Range
): DocumentClassName[] {
const classLists = findClassListsInRange(doc, range)
return [].concat.apply(
[],
classLists.map(({ classList, range }) => {
const parts = classList.split(/(\s+)/)
const names: DocumentClassName[] = []
let index = 0
for (let i = 0; i < parts.length; i++) {
if (i % 2 === 0) {
const start = indexToPosition(classList, index)
const end = indexToPosition(classList, index + parts[i].length)
names.push({
className: parts[i],
range: {
start: {
line: range.start.line + start.line,
character:
(end.line === 0 ? range.start.character : 0) +
start.character,
},
end: {
line: range.start.line + end.line,
character:
(end.line === 0 ? range.start.character : 0) + end.character,
},
},
})
}
index += parts[i].length
}
return names
})
)
}
export function findClassListsInRange(
doc: TextDocument,
range: Range
): DocumentClassList[] {
const text = doc.getText(range)
const matches = findAll(/(@apply\s+)(?<classList>[^;}]+)[;}]/g, text)
return matches.map((match) => {
const start = indexToPosition(text, match.index + match[1].length)
const end = indexToPosition(
text,
match.index + match[1].length + match.groups.classList.length
)
return {
classList: match.groups.classList,
range: {
start: {
line: range.start.line + start.line,
character: range.start.character + start.character,
},
end: {
line: range.start.line + end.line,
character: range.start.character + end.character,
},
},
}
})
}
function indexToPosition(str: string, index: number): Position {
const { line, col } = lineColumn(str + '\n', index)
return { line: line - 1, character: col - 1 }
}
|