add class list finder helper and fix ranges
parent
d6b5a897ac
commit
02683ece85
|
@ -12,7 +12,7 @@ export const CSS_LANGUAGES = [
|
|||
'sugarss',
|
||||
]
|
||||
|
||||
function isCssDoc(state: State, doc: TextDocument): boolean {
|
||||
export function isCssDoc(state: State, doc: TextDocument): boolean {
|
||||
const userCssLanguages = Object.keys(
|
||||
state.editor.userLanguages
|
||||
).filter((lang) => CSS_LANGUAGES.includes(state.editor.userLanguages[lang]))
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { TextDocument, Range, Position } from 'vscode-languageserver'
|
||||
import { DocumentClassName, DocumentClassList, State } from './state'
|
||||
import lineColumn from 'line-column'
|
||||
import { isCssContext } from './css'
|
||||
import { isHtmlContext } from './html'
|
||||
import { isCssContext, isCssDoc } from './css'
|
||||
import { isHtmlContext, isHtmlDoc, isSvelteDoc, isVueDoc } from './html'
|
||||
import { isWithinRange } from './isWithinRange'
|
||||
import { isJsContext } from './js'
|
||||
import { isJsContext, isJsDoc } from './js'
|
||||
import { getClassAttributeLexer } from './lexers'
|
||||
|
||||
export function findAll(re: RegExp, str: string): RegExpMatchArray[] {
|
||||
|
@ -26,8 +26,8 @@ export function findLast(re: RegExp, str: string): RegExpMatchArray {
|
|||
|
||||
export function findClassNamesInRange(
|
||||
doc: TextDocument,
|
||||
range: Range,
|
||||
mode: 'html' | 'css'
|
||||
range?: Range,
|
||||
mode?: 'html' | 'css'
|
||||
): DocumentClassName[] {
|
||||
const classLists = findClassListsInRange(doc, range, mode)
|
||||
return [].concat.apply(
|
||||
|
@ -66,10 +66,11 @@ export function findClassNamesInRange(
|
|||
|
||||
export function findClassListsInCssRange(
|
||||
doc: TextDocument,
|
||||
range: Range
|
||||
range?: Range
|
||||
): DocumentClassList[] {
|
||||
const text = doc.getText(range)
|
||||
const matches = findAll(/(@apply\s+)(?<classList>[^;}]+)[;}]/g, text)
|
||||
const globalStart: Position = range ? range.start : { line: 0, character: 0 }
|
||||
|
||||
return matches.map((match) => {
|
||||
const start = indexToPosition(text, match.index + match[1].length)
|
||||
|
@ -81,12 +82,14 @@ export function findClassListsInCssRange(
|
|||
classList: match.groups.classList,
|
||||
range: {
|
||||
start: {
|
||||
line: range.start.line + start.line,
|
||||
character: range.start.character + start.character,
|
||||
line: globalStart.line + start.line,
|
||||
character:
|
||||
(end.line === 0 ? globalStart.character : 0) + start.character,
|
||||
},
|
||||
end: {
|
||||
line: range.start.line + end.line,
|
||||
character: range.start.character + end.character,
|
||||
line: globalStart.line + end.line,
|
||||
character:
|
||||
(end.line === 0 ? globalStart.character : 0) + end.character,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -172,11 +175,14 @@ export function findClassListsInHtmlRange(
|
|||
range: {
|
||||
start: {
|
||||
line: range.start.line + start.line,
|
||||
character: range.start.character + start.character,
|
||||
character:
|
||||
(end.line === 0 ? range.start.character : 0) +
|
||||
start.character,
|
||||
},
|
||||
end: {
|
||||
line: range.start.line + end.line,
|
||||
character: range.start.character + end.character,
|
||||
character:
|
||||
(end.line === 0 ? range.start.character : 0) + end.character,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -199,6 +205,80 @@ export function findClassListsInRange(
|
|||
return findClassListsInHtmlRange(doc, range)
|
||||
}
|
||||
|
||||
export function findClassListsInDocument(
|
||||
state: State,
|
||||
doc: TextDocument
|
||||
): DocumentClassList[] {
|
||||
if (isCssDoc(state, doc)) {
|
||||
return findClassListsInCssRange(doc)
|
||||
}
|
||||
|
||||
if (isVueDoc(doc)) {
|
||||
let text = doc.getText()
|
||||
let blocks = findAll(
|
||||
/<(?<type>template|style|script)\b[^>]*>.*?(<\/\k<type>>|$)/gis,
|
||||
text
|
||||
)
|
||||
let htmlRanges: Range[] = []
|
||||
let cssRanges: Range[] = []
|
||||
for (let i = 0; i < blocks.length; i++) {
|
||||
let range = {
|
||||
start: indexToPosition(text, blocks[i].index),
|
||||
end: indexToPosition(text, blocks[i].index + blocks[i][0].length),
|
||||
}
|
||||
if (blocks[i].groups.type === 'style') {
|
||||
cssRanges.push(range)
|
||||
} else {
|
||||
htmlRanges.push(range)
|
||||
}
|
||||
}
|
||||
return [].concat.apply(
|
||||
[],
|
||||
[
|
||||
...htmlRanges.map((range) => findClassListsInHtmlRange(doc, range)),
|
||||
...cssRanges.map((range) => findClassListsInCssRange(doc, range)),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
if (isHtmlDoc(state, doc) || isJsDoc(state, doc) || isSvelteDoc(doc)) {
|
||||
let text = doc.getText()
|
||||
let styleBlocks = findAll(/<style(?:\s[^>]*>|>).*?(<\/style>|$)/gis, text)
|
||||
let htmlRanges: Range[] = []
|
||||
let cssRanges: Range[] = []
|
||||
let currentIndex = 0
|
||||
|
||||
for (let i = 0; i < styleBlocks.length; i++) {
|
||||
htmlRanges.push({
|
||||
start: indexToPosition(text, currentIndex),
|
||||
end: indexToPosition(text, styleBlocks[i].index),
|
||||
})
|
||||
cssRanges.push({
|
||||
start: indexToPosition(text, styleBlocks[i].index),
|
||||
end: indexToPosition(
|
||||
text,
|
||||
styleBlocks[i].index + styleBlocks[i][0].length
|
||||
),
|
||||
})
|
||||
currentIndex = styleBlocks[i].index + styleBlocks[i][0].length
|
||||
}
|
||||
htmlRanges.push({
|
||||
start: indexToPosition(text, currentIndex),
|
||||
end: indexToPosition(text, text.length),
|
||||
})
|
||||
|
||||
return [].concat.apply(
|
||||
[],
|
||||
[
|
||||
...htmlRanges.map((range) => findClassListsInHtmlRange(doc, range)),
|
||||
...cssRanges.map((range) => findClassListsInCssRange(doc, range)),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
function indexToPosition(str: string, index: number): Position {
|
||||
const { line, col } = lineColumn(str + '\n', index)
|
||||
return { line: line - 1, character: col - 1 }
|
||||
|
|
Loading…
Reference in New Issue