Skip to content

Commit 02683ec

Browse files
author
Brad Cornes
committed
add class list finder helper and fix ranges
1 parent d6b5a89 commit 02683ec

File tree

2 files changed

+93
-13
lines changed

2 files changed

+93
-13
lines changed

src/lsp/util/css.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export const CSS_LANGUAGES = [
1212
'sugarss',
1313
]
1414

15-
function isCssDoc(state: State, doc: TextDocument): boolean {
15+
export function isCssDoc(state: State, doc: TextDocument): boolean {
1616
const userCssLanguages = Object.keys(
1717
state.editor.userLanguages
1818
).filter((lang) => CSS_LANGUAGES.includes(state.editor.userLanguages[lang]))

src/lsp/util/find.ts

Lines changed: 92 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { TextDocument, Range, Position } from 'vscode-languageserver'
22
import { DocumentClassName, DocumentClassList, State } from './state'
33
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'
66
import { isWithinRange } from './isWithinRange'
7-
import { isJsContext } from './js'
7+
import { isJsContext, isJsDoc } from './js'
88
import { getClassAttributeLexer } from './lexers'
99

1010
export function findAll(re: RegExp, str: string): RegExpMatchArray[] {
@@ -26,8 +26,8 @@ export function findLast(re: RegExp, str: string): RegExpMatchArray {
2626

2727
export function findClassNamesInRange(
2828
doc: TextDocument,
29-
range: Range,
30-
mode: 'html' | 'css'
29+
range?: Range,
30+
mode?: 'html' | 'css'
3131
): DocumentClassName[] {
3232
const classLists = findClassListsInRange(doc, range, mode)
3333
return [].concat.apply(
@@ -66,10 +66,11 @@ export function findClassNamesInRange(
6666

6767
export function findClassListsInCssRange(
6868
doc: TextDocument,
69-
range: Range
69+
range?: Range
7070
): DocumentClassList[] {
7171
const text = doc.getText(range)
7272
const matches = findAll(/(@apply\s+)(?<classList>[^;}]+)[;}]/g, text)
73+
const globalStart: Position = range ? range.start : { line: 0, character: 0 }
7374

7475
return matches.map((match) => {
7576
const start = indexToPosition(text, match.index + match[1].length)
@@ -81,12 +82,14 @@ export function findClassListsInCssRange(
8182
classList: match.groups.classList,
8283
range: {
8384
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,
8688
},
8789
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,
9093
},
9194
},
9295
}
@@ -172,11 +175,14 @@ export function findClassListsInHtmlRange(
172175
range: {
173176
start: {
174177
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,
176181
},
177182
end: {
178183
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,
180186
},
181187
},
182188
}
@@ -199,6 +205,80 @@ export function findClassListsInRange(
199205
return findClassListsInHtmlRange(doc, range)
200206
}
201207

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>template|style|script)\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(/<style(?:\s[^>]*>|>).*?(<\/style>|$)/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+
202282
function indexToPosition(str: string, index: number): Position {
203283
const { line, col } = lineColumn(str + '\n', index)
204284
return { line: line - 1, character: col - 1 }

0 commit comments

Comments
 (0)