tailwind-ctp-intellisense @master -
refs -
log -
-
https://git.jolheiser.com/tailwind-ctp-intellisense.git
Tailwind intellisense + Catppuccin
add `classAttributes` setting
5 changed files, 53 additions(+), 14 deletions(-)
diff --git a/packages/tailwindcss-language-service/src/completionProvider.ts b/packages/tailwindcss-language-service/src/completionProvider.ts
index 94102237e8fd87bd615323c627523a1bc3c4968d..f5d361455c387057be39534126ccb64e72d26406 100644
--- a/packages/tailwindcss-language-service/src/completionProvider.ts
+++ b/packages/tailwindcss-language-service/src/completionProvider.ts
@@ -14,7 +14,7 @@ import removeMeta from './util/removeMeta'
import { getColor, getColorFromValue } from './util/color'
import { isHtmlContext } from './util/html'
import { isCssContext } from './util/css'
-import { findLast } from './util/find'
+import { findLast, matchClassAttributes } from './util/find'
import { stringifyConfigValue, stringifyCss } from './util/stringify'
import { stringifyScreen, Screen } from './util/screens'
import isObject from './util/isObject'
@@ -327,25 +327,30 @@ }),
}
}
-function provideClassAttributeCompletions(
+async function provideClassAttributeCompletions(
state: State,
document: TextDocument,
position: Position,
context?: CompletionContext
-): CompletionList {
+): Promise<CompletionList> {
let str = document.getText({
start: document.positionAt(Math.max(0, document.offsetAt(position) - 500)),
end: position,
})
- const match = findLast(/(?:\s|:|\()(?:class(?:Name)?|\[ngClass\])\s*=\s*['"`{]/gi, str)
+ let matches = matchClassAttributes(
+ str,
+ (await state.editor.getConfiguration(document.uri)).tailwindCSS.classAttributes
+ )
- if (match === null) {
+ if (matches.length === 0) {
return null
}
+ let match = matches[matches.length - 1]
+
const lexer =
- match[0][0] === ':' || match[0].trim().startsWith('[ngClass]')
+ match[0][0] === ':' || (match[1].startsWith('[') && match[1].endsWith(']'))
? getComputedClassAttributeLexer()
: getClassAttributeLexer()
lexer.reset(str.substr(match.index + match[0].length - 1))
@@ -490,12 +495,12 @@ }
)
}
-function provideClassNameCompletions(
+async function provideClassNameCompletions(
state: State,
document: TextDocument,
position: Position,
context?: CompletionContext
-): CompletionList {
+): Promise<CompletionList> {
if (isCssContext(state, document, position)) {
return provideAtApplyCompletions(state, document, position)
}
@@ -1035,7 +1040,7 @@ ) {
if (state === null) return { items: [], isIncomplete: false }
const result =
- provideClassNameCompletions(state, document, position, context) ||
+ (await provideClassNameCompletions(state, document, position, context)) ||
provideCssHelperCompletions(state, document, position) ||
provideCssDirectiveCompletions(state, document, position) ||
provideScreenDirectiveCompletions(state, document, position) ||
diff --git a/packages/tailwindcss-language-service/src/util/find.ts b/packages/tailwindcss-language-service/src/util/find.ts
index 6224cc50b45c7ac5ec5f5cf77d09836a0904e509..a522de0d18855a37afbc86e73b529d2be3ef9cfe 100644
--- a/packages/tailwindcss-language-service/src/util/find.ts
+++ b/packages/tailwindcss-language-service/src/util/find.ts
@@ -172,16 +172,31 @@
return result
}
-export function findClassListsInHtmlRange(doc: TextDocument, range?: Range): DocumentClassList[] {
+export function matchClassAttributes(text: string, attributes: string[]): RegExpMatchArray[] {
+ const attrs = attributes.filter((x) => typeof x === 'string').flatMap((a) => [a, `\\[${a}\\]`])
+ const re = /(?:\s|:|\()(ATTRS)\s*=\s*['"`{]/
+ return findAll(new RegExp(re.source.replace('ATTRS', attrs.join('|')), 'gi'), text)
+}
+
+export async function findClassListsInHtmlRange(
+ state: State,
+ doc: TextDocument,
+ range?: Range
+): Promise<DocumentClassList[]> {
const text = doc.getText(range)
- const matches = findAll(/(?:\s|:|\()(?:class(?:Name)?|\[ngClass\])\s*=\s*['"`{]/gi, text)
+
+ const matches = matchClassAttributes(
+ text,
+ (await state.editor.getConfiguration(doc.uri)).tailwindCSS.classAttributes
+ )
+
const result: DocumentClassList[] = []
matches.forEach((match) => {
const subtext = text.substr(match.index + match[0].length - 1)
let lexer =
- match[0][0] === ':' || match[0].trim().startsWith('[ngClass]')
+ match[0][0] === ':' || (match[1].startsWith('[') && match[1].endsWith(']'))
? getComputedClassAttributeLexer()
: getClassAttributeLexer()
lexer.reset(subtext)
@@ -273,7 +288,7 @@ let classLists: DocumentClassList[]
if (mode === 'css') {
classLists = findClassListsInCssRange(doc, range)
} else {
- classLists = findClassListsInHtmlRange(doc, range)
+ classLists = await findClassListsInHtmlRange(state, doc, range)
}
return [...classLists, ...(includeCustom ? await findCustomClassLists(state, doc, range) : [])]
}
@@ -290,7 +305,9 @@ let boundaries = getLanguageBoundaries(state, doc)
if (!boundaries) return []
return flatten([
- ...boundaries.html.map((range) => findClassListsInHtmlRange(doc, range)),
+ ...(await Promise.all(
+ boundaries.html.map((range) => findClassListsInHtmlRange(state, doc, range))
+ )),
...boundaries.css.map((range) => findClassListsInCssRange(doc, range)),
await findCustomClassLists(state, doc),
])
diff --git a/packages/tailwindcss-language-service/src/util/state.ts b/packages/tailwindcss-language-service/src/util/state.ts
index 2cb86caa4507b659f2ff36f44995d2c0173e9a95..d24c995a6985d71666304d2d8a0c471bc78334fc 100644
--- a/packages/tailwindcss-language-service/src/util/state.ts
+++ b/packages/tailwindcss-language-service/src/util/state.ts
@@ -39,6 +39,7 @@ }
tailwindCSS: {
emmetCompletions: boolean
includeLanguages: Record<string, string>
+ classAttributes: string[]
validate: boolean
showPixelEquivalents: boolean
rootFontSize: number
diff --git a/packages/vscode-tailwindcss/README.md b/packages/vscode-tailwindcss/README.md
index cc86c5ef274df1e56603eabecce608c844e1feb6..8ae89151480adb6b95a0e90ffd42c8c5791df400 100644
--- a/packages/vscode-tailwindcss/README.md
+++ b/packages/vscode-tailwindcss/README.md
@@ -66,6 +66,10 @@ ### `tailwindCSS.emmetCompletions`
Enable completions when using [Emmet](https://emmet.io/)-style syntax, for example `div.bg-red-500.uppercase`. **Default: `false`**
+### `tailwindCSS.classAttributes`
+
+The HTML attributes for which to provide class completions, hover previews, linting etc. **Default: `class`, `className`, `ngClass`**
+
### `tailwindCSS.colorDecorators`
Controls whether the editor should render inline color decorators for Tailwind CSS classes and helper functions. **Default: `true`**
diff --git a/packages/vscode-tailwindcss/package.json b/packages/vscode-tailwindcss/package.json
index 2bbbdec6c16d36c228a81a7cc7c7ae002941f505..ac731fa20ddfb2f028c7e871d47f7484d0f2c2f9 100755
--- a/packages/vscode-tailwindcss/package.json
+++ b/packages/vscode-tailwindcss/package.json
@@ -81,6 +81,18 @@ },
"default": {},
"markdownDescription": "Enable features in languages that are not supported by default. Add a mapping here between the new language and an already supported language.\n E.g.: `{\"plaintext\": \"html\"}`"
},
+ "tailwindCSS.classAttributes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "default": [
+ "class",
+ "className",
+ "ngClass"
+ ],
+ "markdownDescription": "The HTML attributes for which to provide class completions, hover previews, linting etc."
+ },
"tailwindCSS.colorDecorators": {
"type": "boolean",
"default": true,