Fix CSS conflict diagnostics in semicolonless CSS documents (#771)

master
Brad Cornes 2023-04-27 18:17:13 +01:00 committed by GitHub
parent 8266d6b0aa
commit 9b47dd0597
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 14 deletions

View File

@ -8,6 +8,7 @@ import * as semver from '../util/semver'
import { closest } from '../util/closest'
import { absoluteRange } from '../util/absoluteRange'
import { getTextWithoutComments } from '../util/doc'
import { isSemicolonlessCssLanguage } from '../util/languages'
export function getInvalidTailwindDirectiveDiagnostics(
state: State,
@ -28,13 +29,8 @@ export function getInvalidTailwindDirectiveDiagnostics(
ranges.push(...boundaries.filter((b) => b.type === 'css').map(({ range }) => range))
}
let notSemicolonLanguages = ['sass', 'sugarss', 'stylus']
let regex: RegExp
if (
notSemicolonLanguages.includes(document.languageId) ||
(state.editor &&
notSemicolonLanguages.includes(state.editor.userLanguages[document.languageId]))
) {
if (isSemicolonlessCssLanguage(document.languageId, state.editor?.userLanguages)) {
regex = /(?:\s|^)@tailwind\s+(?<value>[^\r\n]+)/g
} else {
regex = /(?:\s|^)@tailwind\s+(?<value>[^;]+)/g

View File

@ -11,6 +11,7 @@ import { getLanguageBoundaries } from './getLanguageBoundaries'
import { resolveRange } from './resolveRange'
import Regex from 'becke-ch--regex--s0-0-v1--base--pl--lib'
import { getTextWithoutComments } from './doc'
import { isSemicolonlessCssLanguage } from './languages'
export function findAll(re: RegExp, str: string): RegExpMatchArray[] {
let match: RegExpMatchArray
@ -91,12 +92,16 @@ export async function findClassNamesInDocument(
)
}
export function findClassListsInCssRange(doc: TextDocument, range?: Range): DocumentClassList[] {
export function findClassListsInCssRange(
state: State,
doc: TextDocument,
range?: Range
): DocumentClassList[] {
const text = getTextWithoutComments(doc, 'css', range)
const matches = findAll(
/(@apply\s+)(?<classList>[^;}]+?)(?<important>\s*!important)?\s*[;}]/g,
text
)
let regex = isSemicolonlessCssLanguage(doc.languageId, state.editor?.userLanguages)
? /(@apply\s+)(?<classList>[^}\r\n]+?)(?<important>\s*!important)?(?:\r|\n|}|$)/g
: /(@apply\s+)(?<classList>[^;}]+?)(?<important>\s*!important)?\s*[;}]/g
const matches = findAll(regex, text)
const globalStart: Position = range ? range.start : { line: 0, character: 0 }
return matches.map((match) => {
@ -292,7 +297,7 @@ export async function findClassListsInRange(
): Promise<DocumentClassList[]> {
let classLists: DocumentClassList[]
if (mode === 'css') {
classLists = findClassListsInCssRange(doc, range)
classLists = findClassListsInCssRange(state, doc, range)
} else {
classLists = await findClassListsInHtmlRange(state, doc, mode, range)
}
@ -307,7 +312,7 @@ export async function findClassListsInDocument(
doc: TextDocument
): Promise<DocumentClassList[]> {
if (isCssDoc(state, doc)) {
return findClassListsInCssRange(doc)
return findClassListsInCssRange(state, doc)
}
let boundaries = getLanguageBoundaries(state, doc)
@ -324,7 +329,7 @@ export async function findClassListsInDocument(
)),
...boundaries
.filter((b) => b.type === 'css')
.map(({ range }) => findClassListsInCssRange(doc, range)),
.map(({ range }) => findClassListsInCssRange(state, doc, range)),
await findCustomClassLists(state, doc),
])
)

View File

@ -1,3 +1,5 @@
import type { EditorState } from './state'
export const htmlLanguages = [
'aspnetcorerazor',
'astro',
@ -57,3 +59,15 @@ export const jsLanguages = [
export const specialLanguages = ['vue', 'svelte']
export const languages = [...cssLanguages, ...htmlLanguages, ...jsLanguages, ...specialLanguages]
const semicolonlessLanguages = ['sass', 'sugarss', 'stylus']
export function isSemicolonlessCssLanguage(
languageId: string,
userLanguages: EditorState['userLanguages'] = {}
) {
return (
semicolonlessLanguages.includes(languageId) ||
semicolonlessLanguages.includes(userLanguages[languageId])
)
}