Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,088 changes: 1,142 additions & 946 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/tailwindcss-language-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"@tailwindcss/typography": "0.5.0",
"@types/debounce": "1.2.0",
"@types/node": "14.14.34",
"@types/vscode": "1.60.0",
"@types/vscode": "1.67.0",
"builtin-modules": "3.2.0",
"chokidar": "3.5.1",
"color-name": "1.1.4",
Expand All @@ -65,7 +65,7 @@
"stack-trace": "0.0.10",
"tailwindcss": "3.0.11",
"terser": "4.6.12",
"typescript": "4.2.4",
"typescript": "4.6.4",
"vscode-css-languageservice": "5.4.1",
"vscode-languageserver": "7.0.0",
"vscode-languageserver-textdocument": "1.0.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/tailwindcss-language-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@
"prettier": "2.3.0",
"tsdx": "0.14.1",
"tslib": "2.2.0",
"typescript": "4.2.4"
"typescript": "4.6.4"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -364,10 +364,10 @@ async function provideClassAttributeCompletions(
try {
let tokens = Array.from(lexer)
let last = tokens[tokens.length - 1]
if (last.type.startsWith('start') || last.type === 'classlist') {
if (last.type.startsWith('start') || last.type === 'classlist' || last.type.startsWith('arb')) {
let classList = ''
for (let i = tokens.length - 1; i >= 0; i--) {
if (tokens[i].type === 'classlist') {
if (tokens[i].type === 'classlist' || tokens[i].type.startsWith('arb')) {
classList = tokens[i].value + classList
} else {
break
Expand Down
2 changes: 1 addition & 1 deletion packages/tailwindcss-language-service/src/util/find.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ export async function findClassListsInHtmlRange(

try {
for (let token of lexer) {
if (token.type === 'classlist') {
if (token.type === 'classlist' || token.type.startsWith('arb')) {
if (currentClassList) {
currentClassList.value += token.value
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,94 @@
import { State } from './state'
import * as jit from './jit'

export function getVariantsFromClassName(
state: State,
className: string
): { variants: string[]; offset: number } {
let str = className
let allVariants = Object.keys(state.variants)
let allVariantsByLength = allVariants.sort((a, b) => b.length - a.length)
let parts = Array.from(splitAtTopLevelOnly(className, state.separator)).filter(Boolean)
let variants = new Set<string>()
let offset = 0

while (str) {
let found = false
for (let variant of allVariantsByLength) {
if (str.startsWith(variant + state.separator)) {
variants.add(variant)
str = str.substr(variant.length + state.separator.length)
offset += variant.length + state.separator.length
found = true
break
}
for (let part of parts) {
if (
allVariants.includes(part) ||
(state.jit &&
part.startsWith('[') &&
part.endsWith(']') &&
jit.generateRules(state, [`${part}${state.separator}[color:red]`]).rules.length > 0)
) {
variants.add(part)
offset += part.length + state.separator.length
continue
}
if (!found) str = ''

break
}

return { variants: Array.from(variants), offset }
}

const REGEX_SPECIAL = /[\\^$.*+?()[\]{}|]/g
const REGEX_HAS_SPECIAL = RegExp(REGEX_SPECIAL.source)

function regexEscape(string: string): string {
return string && REGEX_HAS_SPECIAL.test(string)
? string.replace(REGEX_SPECIAL, '\\$&')
: string || ''
}

function* splitAtTopLevelOnly(input: string, separator: string): Generator<string> {
let SPECIALS = new RegExp(`[(){}\\[\\]${regexEscape(separator)}]`, 'g')

let depth = 0
let lastIndex = 0
let found = false
let separatorIndex = 0
let separatorStart = 0
let separatorLength = separator.length

// Find all paren-like things & character
// And only split on commas if they're top-level
for (let match of input.matchAll(SPECIALS)) {
let matchesSeparator = match[0] === separator[separatorIndex]
let atEndOfSeparator = separatorIndex === separatorLength - 1
let matchesFullSeparator = matchesSeparator && atEndOfSeparator

if (match[0] === '(') depth++
if (match[0] === ')') depth--
if (match[0] === '[') depth++
if (match[0] === ']') depth--
if (match[0] === '{') depth++
if (match[0] === '}') depth--

if (matchesSeparator && depth === 0) {
if (separatorStart === 0) {
separatorStart = match.index
}

separatorIndex++
}

if (matchesFullSeparator && depth === 0) {
found = true

yield input.substring(lastIndex, separatorStart)
lastIndex = separatorStart + separatorLength
}

if (separatorIndex === separatorLength) {
separatorIndex = 0
separatorStart = 0
}
}

// Provide the last segment of the string if available
// Otherwise the whole string since no `char`s were found
// This mirrors the behavior of string.split()
if (found) {
yield input.substring(lastIndex)
} else {
yield input
}
}
6 changes: 6 additions & 0 deletions packages/tailwindcss-language-service/src/util/lexers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { lazy } from './lazy'

const classAttributeStates: () => { [x: string]: moo.Rules } = () => ({
doubleClassList: {
arb: { match: new RegExp('(?<!\\\\)\\['), push: 'arbitrary' },
lbrace: { match: new RegExp('(?<!\\\\)\\{'), push: 'interpBrace' },
rbrace: { match: new RegExp('(?<!\\\\)\\}'), pop: 1 },
end: { match: new RegExp('(?<!\\\\)"'), pop: 1 },
Expand Down Expand Up @@ -40,6 +41,11 @@ const classAttributeStates: () => { [x: string]: moo.Rules } = () => ({
double: { match: new RegExp('(?<!\\\\)"'), pop: 1 },
text: { match: new RegExp('[\\s\\S]'), lineBreaks: true },
},
arbitrary: {
arb: { match: new RegExp('(?<!\\\\)\\]'), pop: 1 },
space: { match: /\s/, pop: 1, lineBreaks: true },
arb2: { match: new RegExp('[\\s\\S]'), lineBreaks: true },
},
})

const simpleClassAttributeStates: { [x: string]: moo.Rules } = {
Expand Down
2 changes: 1 addition & 1 deletion packages/vscode-tailwindcss/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@
"check": "tsc --noEmit"
},
"devDependencies": {
"@types/vscode": "1.60.0",
"@types/vscode": "1.67.0",
"color-name": "1.1.4",
"concurrently": "7.0.0",
"rimraf": "3.0.2",
Expand Down