Skip to content

Commit 2c05f5d

Browse files
committed
improve support for tailwindcss v2
1 parent 0cce870 commit 2c05f5d

File tree

11 files changed

+24390
-96
lines changed

11 files changed

+24390
-96
lines changed

packages/tailwindcss-intellisense/package-lock.json

Lines changed: 24257 additions & 0 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: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
"preview": true,
66
"author": "Brad Cornes <hello@bradley.dev>",
77
"license": "MIT",
8-
"version": "0.4.3",
9-
"homepage": "https://github.com/tailwindcss/intellisense",
8+
"version": "0.5.0",
9+
"homepage": "https://github.com/tailwindlabs/tailwindcss-intellisense",
1010
"bugs": {
11-
"url": "https://github.com/tailwindcss/intellisense/issues",
11+
"url": "https://github.com/tailwindlabs/tailwindcss-intellisense/issues",
1212
"email": "hello@bradley.dev"
1313
},
1414
"repository": {
1515
"type": "git",
16-
"url": "https://github.com/tailwindcss/intellisense.git"
16+
"url": "https://github.com/tailwindlabs/tailwindcss-intellisense.git"
1717
},
1818
"publisher": "bradlc",
1919
"keywords": [
@@ -177,6 +177,7 @@
177177
"@types/node": "^13.9.3",
178178
"@types/vscode": "^1.32.0",
179179
"@zeit/ncc": "^0.22.0",
180+
"bufferutil": "^4.0.2",
180181
"callsite": "^1.0.0",
181182
"chokidar": "^3.3.1",
182183
"debounce": "^1.2.0",
@@ -196,11 +197,12 @@
196197
"rimraf": "^3.0.2",
197198
"semver": "^7.3.2",
198199
"stack-trace": "0.0.10",
199-
"tailwindcss-language-service": "0.0.3",
200+
"tailwindcss-language-service": "0.0.4",
200201
"terser": "^4.6.12",
201202
"tiny-invariant": "^1.1.0",
202203
"tslint": "^5.16.0",
203204
"typescript": "^3.8.3",
205+
"utf-8-validate": "^5.0.3",
204206
"vsce": "^1.76.1",
205207
"vscode-languageclient": "^6.1.3",
206208
"vscode-languageserver": "^6.1.1",

packages/tailwindcss-intellisense/src/class-names/extractClassNames.js

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import selectorParser from 'postcss-selector-parser'
2-
import fs from 'fs'
3-
import path from 'path'
42
import dset from 'dset'
53
import dlv from 'dlv'
64

@@ -83,48 +81,43 @@ async function process(groups) {
8381
const contextKeys = baseKeys.slice(0, baseKeys.length - 1)
8482
const index = []
8583

86-
const existing = dlv(tree, baseKeys)
84+
const existing = dlv(tree, [...baseKeys, '__info'])
8785
if (typeof existing !== 'undefined') {
8886
if (Array.isArray(existing)) {
89-
const scopeIndex = existing.findIndex(
90-
(x) =>
91-
x.__scope === classNames[i].scope &&
92-
arraysEqual(existing.__context, context)
93-
)
94-
if (scopeIndex > -1) {
95-
keys.unshift(scopeIndex)
96-
index.push(scopeIndex)
97-
} else {
98-
keys.unshift(existing.length)
99-
index.push(existing.length)
100-
}
87+
index.push(existing.length)
10188
} else {
102-
if (
103-
existing.__scope !== classNames[i].scope ||
104-
!arraysEqual(existing.__context, context)
105-
) {
106-
dset(tree, baseKeys, [existing])
107-
keys.unshift(1)
108-
index.push(1)
109-
}
89+
dset(tree, [...baseKeys, '__info'], [existing])
90+
index.push(1)
11091
}
11192
}
11293
if (classNames[i].__rule) {
113-
dset(tree, [...baseKeys, ...index, '__rule'], true)
114-
dset(tree, [...baseKeys, ...index, '__source'], group.source)
115-
116-
dsetEach(tree, [...baseKeys, ...index], decls)
94+
dset(tree, [...baseKeys, '__info', ...index, '__rule'], true)
95+
dset(
96+
tree,
97+
[...baseKeys, '__info', ...index, '__source'],
98+
group.source
99+
)
100+
101+
dsetEach(tree, [...baseKeys, '__info', ...index], decls)
117102
}
118-
dset(tree, [...baseKeys, ...index, '__pseudo'], classNames[i].__pseudo)
119-
dset(tree, [...baseKeys, ...index, '__scope'], classNames[i].scope)
120103
dset(
121104
tree,
122-
[...baseKeys, ...index, '__context'],
105+
[...baseKeys, '__info', ...index, '__pseudo'],
106+
classNames[i].__pseudo
107+
)
108+
dset(
109+
tree,
110+
[...baseKeys, '__info', ...index, '__scope'],
111+
classNames[i].scope
112+
)
113+
dset(
114+
tree,
115+
[...baseKeys, '__info', ...index, '__context'],
123116
context.concat([]).reverse()
124117
)
125118

126119
// common context
127-
context.push(...classNames[i].__pseudo)
120+
context.push(...classNames[i].__pseudo.map((x) => `&${x}`))
128121

129122
for (let i = 0; i < contextKeys.length; i++) {
130123
if (typeof commonContext[contextKeys[i]] === 'undefined') {

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

Lines changed: 2 additions & 2 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 & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "tailwindcss-language-service",
3-
"version": "0.0.3",
3+
"version": "0.0.4",
44
"main": "dist/index.js",
55
"typings": "dist/index.d.ts",
66
"files": [

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

Lines changed: 83 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ function completionsFromClassList(
5757
for (let i = parts.length - 1; i > 0; i--) {
5858
let keys = parts.slice(0, i).filter(Boolean)
5959
subset = dlv(state.classNames.classNames, keys)
60-
if (typeof subset !== 'undefined' && typeof subset.__rule === 'undefined') {
60+
if (
61+
typeof subset !== 'undefined' &&
62+
typeof dlv(subset, ['__info', '__rule']) === 'undefined'
63+
) {
6164
isSubset = true
6265
subsetKey = keys
6366
replacementRange = {
@@ -74,50 +77,75 @@ function completionsFromClassList(
7477
}
7578
}
7679

80+
// console.log(Object.keys(isSubset ? subset : state.classNames.classNames))
81+
7782
return {
7883
isIncomplete: false,
7984
items: Object.keys(isSubset ? subset : state.classNames.classNames)
80-
.map((className, index) => {
81-
let label = className
82-
let kind: CompletionItemKind = 21
83-
let documentation: string = null
84-
let command: any
85-
let sortText = naturalExpand(index)
86-
if (isContextItem(state, [...subsetKey, className])) {
87-
kind = 9
88-
command = { title: '', command: 'editor.action.triggerSuggest' }
89-
label += sep
90-
sortText = '-' + sortText // move to top
91-
} else {
92-
const color = getColor(state, [className])
93-
if (color !== null) {
94-
kind = 16
95-
if (typeof color !== 'string' && color.a !== 0) {
96-
documentation = color.toRgbString()
97-
}
85+
.filter((k) => k !== '__info')
86+
.filter((className) => isContextItem(state, [...subsetKey, className]))
87+
.map(
88+
(className, index): CompletionItem => {
89+
return {
90+
label: className + sep,
91+
kind: 9,
92+
documentation: null,
93+
command: {
94+
title: '',
95+
command: 'editor.action.triggerSuggest',
96+
},
97+
sortText: '-' + naturalExpand(index),
98+
data: [...subsetKey, className],
99+
textEdit: {
100+
newText: className + sep,
101+
range: replacementRange,
102+
},
98103
}
99104
}
105+
)
106+
.concat(
107+
Object.keys(isSubset ? subset : state.classNames.classNames)
108+
.filter((className) =>
109+
dlv(state.classNames.classNames, [
110+
...subsetKey,
111+
className,
112+
'__info',
113+
])
114+
)
115+
.map((className, index) => {
116+
let kind: CompletionItemKind = 21
117+
let documentation: string = null
118+
119+
const color = getColor(state, [className])
120+
if (color !== null) {
121+
kind = 16
122+
if (typeof color !== 'string' && color.a !== 0) {
123+
documentation = color.toRgbString()
124+
}
125+
}
100126

101-
const item = {
102-
label,
103-
kind,
104-
documentation,
105-
command,
106-
sortText,
107-
data: [...subsetKey, className],
108-
textEdit: {
109-
newText: label,
110-
range: replacementRange,
111-
},
127+
return {
128+
label: className,
129+
kind,
130+
documentation,
131+
sortText: naturalExpand(index),
132+
data: [...subsetKey, className],
133+
textEdit: {
134+
newText: className,
135+
range: replacementRange,
136+
},
137+
}
138+
})
139+
)
140+
.filter((item) => {
141+
if (item === null) {
142+
return false
112143
}
113-
114144
if (filter && !filter(item)) {
115-
return null
145+
return false
116146
}
117-
118-
return item
119-
})
120-
.filter((item) => item !== null),
147+
return true
148+
}),
121149
}
122150
}
123151

@@ -199,7 +227,10 @@ function provideAtApplyCompletions(
199227
},
200228
(item) => {
201229
if (item.kind === 9) {
202-
return semver.gte(state.version, '2.0.0-alpha.1') || flagEnabled(state, 'applyComplexClasses')
230+
return (
231+
semver.gte(state.version, '2.0.0-alpha.1') ||
232+
flagEnabled(state, 'applyComplexClasses')
233+
)
203234
}
204235
let validated = validateApply(state, item.data)
205236
return validated !== null && validated.isApplyable === true
@@ -708,8 +739,8 @@ export function resolveCompletionItem(
708739
return item
709740
}
710741

711-
const className = dlv(state.classNames.classNames, item.data)
712-
if (isContextItem(state, item.data)) {
742+
const className = dlv(state.classNames.classNames, [...item.data, '__info'])
743+
if (item.kind === 9) {
713744
item.detail = state.classNames.context[
714745
item.data[item.data.length - 1]
715746
].join(', ')
@@ -729,13 +760,19 @@ export function resolveCompletionItem(
729760
}
730761

731762
function isContextItem(state: State, keys: string[]): boolean {
732-
const item = dlv(state.classNames.classNames, keys)
733-
return Boolean(
734-
isObject(item) &&
735-
!item.__rule &&
736-
!Array.isArray(item) &&
737-
state.classNames.context[keys[keys.length - 1]]
738-
)
763+
const item = dlv(state.classNames.classNames, [keys])
764+
765+
if (!isObject(item)) {
766+
return false
767+
}
768+
if (!state.classNames.context[keys[keys.length - 1]]) {
769+
return false
770+
}
771+
if (Object.keys(item).filter((x) => x !== '__info').length > 0) {
772+
return true
773+
}
774+
775+
return isObject(item.__info) && !item.__info.__rule
739776
}
740777

741778
function stringifyDecls(obj: any): string {

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,17 @@ function provideClassNameHover(
8989
}
9090
}
9191

92+
const css = stringifyCss(
93+
className.className,
94+
dlv(state.classNames.classNames, [...parts, '__info'])
95+
)
96+
97+
if (!css) return null
98+
9299
return {
93100
contents: {
94101
language: 'css',
95-
value: stringifyCss(
96-
className.className,
97-
dlv(state.classNames.classNames, parts)
98-
),
102+
value: css,
99103
},
100104
range: className.range,
101105
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function getColor(
2929
state: State,
3030
keys: string[]
3131
): TinyColor | string | null {
32-
const item = dlv(state.classNames.classNames, keys)
32+
const item = dlv(state.classNames.classNames, [...keys, '__info'])
3333
if (!item.__rule) return null
3434
const props = Object.keys(removeMeta(item))
3535
if (props.length === 0) return null

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ export function getClassNameParts(state: State, className: string): string[] {
88
let parts: string[] = className.split(separator)
99

1010
if (parts.length === 1) {
11-
return dlv(state.classNames.classNames, [className, '__rule']) === true ||
12-
Array.isArray(dlv(state.classNames.classNames, [className]))
11+
return dlv(state.classNames.classNames, [className, '__info', '__rule']) ===
12+
true ||
13+
Array.isArray(dlv(state.classNames.classNames, [className, '__info']))
1314
? [className]
1415
: null
1516
}
@@ -34,8 +35,8 @@ export function getClassNameParts(state: State, className: string): string[] {
3435

3536
return possibilities.find((key) => {
3637
if (
37-
dlv(state.classNames.classNames, [...key, '__rule']) === true ||
38-
Array.isArray(dlv(state.classNames.classNames, [...key]))
38+
dlv(state.classNames.classNames, [...key, '__info', '__rule']) === true ||
39+
Array.isArray(dlv(state.classNames.classNames, [...key, '__info']))
3940
) {
4041
return true
4142
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export function getClassNameDecls(
1010
const parts = getClassNameParts(state, className)
1111
if (!parts) return null
1212

13-
const info = dlv(state.classNames.classNames, parts)
13+
const info = dlv(state.classNames.classNames, [...parts, '__info'])
1414

1515
if (Array.isArray(info)) {
1616
return info.map(removeMeta)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export function getClassNameMeta(
1010
? classNameOrParts
1111
: getClassNameParts(state, classNameOrParts)
1212
if (!parts) return null
13-
const info = dlv(state.classNames.classNames, parts)
13+
const info = dlv(state.classNames.classNames, [...parts, '__info'])
1414

1515
if (Array.isArray(info)) {
1616
return info.map((i) => ({

0 commit comments

Comments
 (0)