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