Skip to content

Commit a4fdd94

Browse files
committed
add experimental classRegex setting (#129)
1 parent 5633349 commit a4fdd94

File tree

7 files changed

+1921
-5558
lines changed

7 files changed

+1921
-5558
lines changed

package-lock.json

Lines changed: 1830 additions & 5557 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/tailwindcss-intellisense/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@
158158
"default": "error",
159159
"markdownDescription": "Unknown value used with the [`@tailwind` directive](https://tailwindcss.com/docs/functions-and-directives/#tailwind)",
160160
"scope": "language-overridable"
161+
},
162+
"tailwindCSS.experimental.classRegex": {
163+
"type": "array",
164+
"scope": "language-overridable"
161165
}
162166
}
163167
}

packages/tailwindcss-intellisense/src/lsp/server.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ const defaultSettings: Settings = {
4646
tabSize: 2,
4747
emmetCompletions: false,
4848
includeLanguages: {},
49+
experimental: {
50+
classRegex: [],
51+
},
4952
validate: true,
5053
lint: {
5154
cssConflict: 'warning',

packages/tailwindcss-language-service/package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/tailwindcss-language-service/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"line-column": "^1.0.2",
2323
"mitt": "^2.1.0",
2424
"moo": "^0.5.1",
25+
"multi-regexp2": "^1.0.3",
2526
"semver": "^7.3.2",
2627
"sift-string": "^0.0.2",
2728
"tsdx": "^0.13.3",

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

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
} from './util/lexers'
3232
import { validateApply } from './util/validateApply'
3333
import { flagEnabled } from './util/flagEnabled'
34+
import MultiRegexp from 'multi-regexp2'
3435

3536
export function completionsFromClassList(
3637
state: State,
@@ -195,6 +196,72 @@ function provideClassAttributeCompletions(
195196
return null
196197
}
197198

199+
async function provideCustomClassNameCompletions(
200+
state: State,
201+
document: TextDocument,
202+
position: Position
203+
): Promise<CompletionList> {
204+
const settings = await getDocumentSettings(state, document)
205+
const regexes = dlv(settings, 'experimental.classRegex', [])
206+
if (regexes.length === 0) return null
207+
208+
const searchRange = {
209+
start: { line: Math.max(position.line - 10, 0), character: 0 },
210+
end: { line: position.line + 10, character: 0 },
211+
}
212+
213+
let str = document.getText(searchRange)
214+
215+
for (let i = 0; i < regexes.length; i++) {
216+
let [containerRegex, classRegex] = Array.isArray(regexes[i])
217+
? regexes[i]
218+
: [regexes[i]]
219+
containerRegex = new MultiRegexp(new RegExp(containerRegex))
220+
try {
221+
const match = containerRegex.execForGroup(str, 1)
222+
if (match === null) {
223+
throw Error()
224+
}
225+
const searchStart = document.offsetAt(searchRange.start)
226+
const matchStart = searchStart + match.start
227+
const matchEnd = searchStart + match.end
228+
const cursor = document.offsetAt(position)
229+
if (cursor >= matchStart && cursor <= matchEnd) {
230+
let classList
231+
232+
if (classRegex) {
233+
classRegex = new MultiRegexp(new RegExp(classRegex, 'g'))
234+
let classMatch
235+
while (
236+
(classMatch = classRegex.execForGroup(match.match, 1)) !== null
237+
) {
238+
const classMatchStart = matchStart + classMatch.start
239+
const classMatchEnd = matchStart + classMatch.end
240+
if (cursor >= classMatchStart && cursor <= classMatchEnd) {
241+
classList = classMatch.match.substr(0, cursor - classMatchStart)
242+
}
243+
}
244+
if (typeof classList === 'undefined') {
245+
throw Error()
246+
}
247+
} else {
248+
classList = match.match.substr(0, cursor - matchStart)
249+
}
250+
251+
return completionsFromClassList(state, classList, {
252+
start: {
253+
line: position.line,
254+
character: position.character - classList.length,
255+
},
256+
end: position,
257+
})
258+
}
259+
} catch (_) {}
260+
}
261+
262+
return null
263+
}
264+
198265
function provideAtApplyCompletions(
199266
state: State,
200267
document: TextDocument,
@@ -711,7 +778,8 @@ export async function doComplete(
711778
provideCssDirectiveCompletions(state, document, position) ||
712779
provideScreenDirectiveCompletions(state, document, position) ||
713780
provideVariantsDirectiveCompletions(state, document, position) ||
714-
provideTailwindDirectiveCompletions(state, document, position)
781+
provideTailwindDirectiveCompletions(state, document, position) ||
782+
(await provideCustomClassNameCompletions(state, document, position))
715783

716784
if (result) return result
717785

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ export type Settings = {
4141
invalidConfigPath: DiagnosticSeveritySetting
4242
invalidTailwindDirective: DiagnosticSeveritySetting
4343
}
44+
experimental: {
45+
classRegex: string[]
46+
}
4447
}
4548

4649
interface NotificationEmitter {

0 commit comments

Comments
 (0)