Skip to content

Commit 39b4a94

Browse files
author
Laurynas Grigutis
committed
Added "tailwindCSS.experimental.classFunctions" option
1 parent c8efeca commit 39b4a94

File tree

6 files changed

+36
-5
lines changed

6 files changed

+36
-5
lines changed

packages/tailwindcss-language-server/src/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ function getDefaultSettings(): Settings {
3737
experimental: {
3838
classRegex: [],
3939
configFile: null,
40+
classFunctions: []
4041
},
4142
},
4243
}

packages/tailwindcss-language-service/src/completionProvider.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import removeMeta from './util/removeMeta'
1515
import { formatColor, getColor, getColorFromValue } from './util/color'
1616
import { isHtmlContext, isHtmlDoc, isVueDoc } from './util/html'
1717
import { isCssContext } from './util/css'
18-
import { findLast, matchClassAttributes } from './util/find'
18+
import { findLast, matchClassAttributes, matchClassFunctions } from './util/find'
1919
import { stringifyConfigValue, stringifyCss } from './util/stringify'
2020
import { stringifyScreen, Screen } from './util/screens'
2121
import isObject from './util/isObject'
@@ -747,6 +747,10 @@ async function provideClassAttributeCompletions(
747747

748748
let matches = matchClassAttributes(str, settings.classAttributes)
749749

750+
if (settings.experimental.classFunctions.length > 0) {
751+
matches.push(...matchClassFunctions(str, settings.experimental.classFunctions))
752+
}
753+
750754
if (matches.length === 0) {
751755
return null
752756
}

packages/tailwindcss-language-service/src/util/find.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,12 @@ export function matchClassAttributes(text: string, attributes: string[]): RegExp
164164
return findAll(new RegExp(re.source.replace('ATTRS', attrs.join('|')), 'gi'), text)
165165
}
166166

167+
export function matchClassFunctions(text: string, fnNames: string[]): RegExpMatchArray[] {
168+
const names = fnNames.filter((x) => typeof x === 'string')
169+
const re = /\b(F_NAMES)\(/
170+
return findAll(new RegExp(re.source.replace('F_NAMES', names.join('|')), 'gi'), text)
171+
}
172+
167173
export async function findClassListsInHtmlRange(
168174
state: State,
169175
doc: TextDocument,
@@ -172,10 +178,12 @@ export async function findClassListsInHtmlRange(
172178
): Promise<DocumentClassList[]> {
173179
const text = getTextWithoutComments(doc, type, range)
174180

175-
const matches = matchClassAttributes(
176-
text,
177-
(await state.editor.getConfiguration(doc.uri)).tailwindCSS.classAttributes,
178-
)
181+
const settings = (await state.editor.getConfiguration(doc.uri)).tailwindCSS
182+
const matches = matchClassAttributes(text, settings.classAttributes)
183+
184+
if (settings.experimental.classFunctions.length > 0) {
185+
matches.push(...matchClassFunctions(text, settings.experimental.classFunctions))
186+
}
179187

180188
const result: DocumentClassList[] = []
181189

packages/tailwindcss-language-service/src/util/lexers.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ const classAttributeStates: () => { [x: string]: moo.Rules } = () => ({
2929
rbrace: { match: new RegExp('(?<!\\\\)\\}'), pop: 1 },
3030
text: { match: new RegExp('[\\s\\S]'), lineBreaks: true },
3131
},
32+
interpParen: {
33+
startSingle: { match: new RegExp("(?<!\\\\)'"), push: 'singleClassList' },
34+
startDouble: { match: new RegExp('(?<!\\\\)"'), push: 'doubleClassList' },
35+
startTick: { match: new RegExp('(?<!\\\\)`'), push: 'tickClassList' },
36+
lbrace: { match: new RegExp('(?<!\\\\)\\('), push: 'interpParen' },
37+
rbrace: { match: new RegExp('(?<!\\\\)\\)'), pop: 1 },
38+
text: { match: new RegExp('[\\s\\S]'), lineBreaks: true },
39+
},
3240
interpSingle: {
3341
startDouble: { match: new RegExp('(?<!\\\\)"'), push: 'doubleClassList' },
3442
startTick: { match: new RegExp('(?<!\\\\)`'), push: 'tickClassList' },
@@ -73,6 +81,7 @@ export const getClassAttributeLexer = lazy(() => {
7381
start2: { match: "'", push: 'singleClassList' },
7482
start3: { match: '{', push: 'interpBrace' },
7583
start4: { match: '`', push: 'tickClassList' },
84+
start5: { match: '(', push: 'interpParen' },
7685
},
7786
...classAttributeStates(),
7887
})

packages/tailwindcss-language-service/src/util/state.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export type TailwindCssSettings = {
6666
experimental: {
6767
classRegex: string[]
6868
configFile: string | Record<string, string | string[]> | null
69+
classFunctions: string[]
6970
}
7071
files: {
7172
exclude: string[]

packages/vscode-tailwindcss/package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,14 @@
304304
"default": null,
305305
"markdownDescription": "Manually specify the Tailwind config file or files that should be read to provide IntelliSense features. Can either be a single string value, or an object where each key is a config file path and each value is a glob or array of globs representing the set of files that the config file applies to."
306306
},
307+
"tailwindCSS.experimental.classFunctions": {
308+
"type": "array",
309+
"items": {
310+
"type": "string"
311+
},
312+
"default": [],
313+
"markdownDescription": "The function names for which to provide class completions, hover previews, linting etc."
314+
},
307315
"tailwindCSS.showPixelEquivalents": {
308316
"type": "boolean",
309317
"default": true,

0 commit comments

Comments
 (0)