Skip to content

Commit 2b4ea36

Browse files
committed
Merge branch 'master' into get-variants
2 parents 001e16b + c9acd0d commit 2b4ea36

File tree

2 files changed

+27
-56
lines changed

2 files changed

+27
-56
lines changed

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -1521,7 +1521,10 @@ class TW {
15211521
resolveProvider: true,
15221522
triggerCharacters: [
15231523
...TRIGGER_CHARACTERS,
1524-
...projects.map((project) => project.state.separator).filter(Boolean),
1524+
...projects
1525+
.map((project) => project.state.separator)
1526+
.filter((sep) => typeof sep === 'string')
1527+
.map((sep) => sep.slice(-1)),
15251528
].filter(Boolean),
15261529
})
15271530

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

+23-55
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export function getVariantsFromClassName(
1111
}
1212
return [variant.name]
1313
})
14-
let parts = Array.from(splitAtTopLevelOnly(className, state.separator)).filter(Boolean)
14+
let parts = splitAtTopLevelOnly(className, state.separator).filter(Boolean)
1515
let variants = new Set<string>()
1616
let offset = 0
1717

@@ -34,66 +34,34 @@ export function getVariantsFromClassName(
3434
return { variants: Array.from(variants), offset }
3535
}
3636

37-
const REGEX_SPECIAL = /[\\^$.*+?()[\]{}|]/g
38-
const REGEX_HAS_SPECIAL = RegExp(REGEX_SPECIAL.source)
37+
// https://github.com/tailwindlabs/tailwindcss/blob/a8a2e2a7191fbd4bee044523aecbade5823a8664/src/util/splitAtTopLevelOnly.js
38+
function splitAtTopLevelOnly(input: string, separator: string): string[] {
39+
let stack: string[] = []
40+
let parts: string[] = []
41+
let lastPos = 0
3942

40-
function regexEscape(string: string): string {
41-
return string && REGEX_HAS_SPECIAL.test(string)
42-
? string.replace(REGEX_SPECIAL, '\\$&')
43-
: string || ''
44-
}
45-
46-
function* splitAtTopLevelOnly(input: string, separator: string): Generator<string> {
47-
let SPECIALS = new RegExp(`[(){}\\[\\]${regexEscape(separator)}]`, 'g')
48-
49-
let depth = 0
50-
let lastIndex = 0
51-
let found = false
52-
let separatorIndex = 0
53-
let separatorStart = 0
54-
let separatorLength = separator.length
43+
for (let idx = 0; idx < input.length; idx++) {
44+
let char = input[idx]
5545

56-
// Find all paren-like things & character
57-
// And only split on commas if they're top-level
58-
for (let match of input.matchAll(SPECIALS)) {
59-
let matchesSeparator = match[0] === separator[separatorIndex]
60-
let atEndOfSeparator = separatorIndex === separatorLength - 1
61-
let matchesFullSeparator = matchesSeparator && atEndOfSeparator
62-
63-
if (match[0] === '(') depth++
64-
if (match[0] === ')') depth--
65-
if (match[0] === '[') depth++
66-
if (match[0] === ']') depth--
67-
if (match[0] === '{') depth++
68-
if (match[0] === '}') depth--
69-
70-
if (matchesSeparator && depth === 0) {
71-
if (separatorStart === 0) {
72-
separatorStart = match.index
46+
if (stack.length === 0 && char === separator[0]) {
47+
if (separator.length === 1 || input.slice(idx, idx + separator.length) === separator) {
48+
parts.push(input.slice(lastPos, idx))
49+
lastPos = idx + separator.length
7350
}
74-
75-
separatorIndex++
7651
}
7752

78-
if (matchesFullSeparator && depth === 0) {
79-
found = true
80-
81-
yield input.substring(lastIndex, separatorStart)
82-
lastIndex = separatorStart + separatorLength
83-
}
84-
85-
if (separatorIndex === separatorLength) {
86-
separatorIndex = 0
87-
separatorStart = 0
53+
if (char === '(' || char === '[' || char === '{') {
54+
stack.push(char)
55+
} else if (
56+
(char === ')' && stack[stack.length - 1] === '(') ||
57+
(char === ']' && stack[stack.length - 1] === '[') ||
58+
(char === '}' && stack[stack.length - 1] === '{')
59+
) {
60+
stack.pop()
8861
}
8962
}
9063

91-
// Provide the last segment of the string if available
92-
// Otherwise the whole string since no `char`s were found
93-
// This mirrors the behavior of string.split()
94-
if (found) {
95-
yield input.substring(lastIndex)
96-
} else {
97-
yield input
98-
}
64+
parts.push(input.slice(lastPos))
65+
66+
return parts
9967
}

0 commit comments

Comments
 (0)