improve support for tailwindcss v2
parent
0cce870c13
commit
2c05f5df3a
File diff suppressed because it is too large
Load Diff
|
@ -5,15 +5,15 @@
|
|||
"preview": true,
|
||||
"author": "Brad Cornes <hello@bradley.dev>",
|
||||
"license": "MIT",
|
||||
"version": "0.4.3",
|
||||
"homepage": "https://github.com/tailwindcss/intellisense",
|
||||
"version": "0.5.0",
|
||||
"homepage": "https://github.com/tailwindlabs/tailwindcss-intellisense",
|
||||
"bugs": {
|
||||
"url": "https://github.com/tailwindcss/intellisense/issues",
|
||||
"url": "https://github.com/tailwindlabs/tailwindcss-intellisense/issues",
|
||||
"email": "hello@bradley.dev"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/tailwindcss/intellisense.git"
|
||||
"url": "https://github.com/tailwindlabs/tailwindcss-intellisense.git"
|
||||
},
|
||||
"publisher": "bradlc",
|
||||
"keywords": [
|
||||
|
@ -177,6 +177,7 @@
|
|||
"@types/node": "^13.9.3",
|
||||
"@types/vscode": "^1.32.0",
|
||||
"@zeit/ncc": "^0.22.0",
|
||||
"bufferutil": "^4.0.2",
|
||||
"callsite": "^1.0.0",
|
||||
"chokidar": "^3.3.1",
|
||||
"debounce": "^1.2.0",
|
||||
|
@ -196,11 +197,12 @@
|
|||
"rimraf": "^3.0.2",
|
||||
"semver": "^7.3.2",
|
||||
"stack-trace": "0.0.10",
|
||||
"tailwindcss-language-service": "0.0.3",
|
||||
"tailwindcss-language-service": "0.0.4",
|
||||
"terser": "^4.6.12",
|
||||
"tiny-invariant": "^1.1.0",
|
||||
"tslint": "^5.16.0",
|
||||
"typescript": "^3.8.3",
|
||||
"utf-8-validate": "^5.0.3",
|
||||
"vsce": "^1.76.1",
|
||||
"vscode-languageclient": "^6.1.3",
|
||||
"vscode-languageserver": "^6.1.1",
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import selectorParser from 'postcss-selector-parser'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import dset from 'dset'
|
||||
import dlv from 'dlv'
|
||||
|
||||
|
@ -83,48 +81,43 @@ async function process(groups) {
|
|||
const contextKeys = baseKeys.slice(0, baseKeys.length - 1)
|
||||
const index = []
|
||||
|
||||
const existing = dlv(tree, baseKeys)
|
||||
const existing = dlv(tree, [...baseKeys, '__info'])
|
||||
if (typeof existing !== 'undefined') {
|
||||
if (Array.isArray(existing)) {
|
||||
const scopeIndex = existing.findIndex(
|
||||
(x) =>
|
||||
x.__scope === classNames[i].scope &&
|
||||
arraysEqual(existing.__context, context)
|
||||
)
|
||||
if (scopeIndex > -1) {
|
||||
keys.unshift(scopeIndex)
|
||||
index.push(scopeIndex)
|
||||
} else {
|
||||
keys.unshift(existing.length)
|
||||
index.push(existing.length)
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
existing.__scope !== classNames[i].scope ||
|
||||
!arraysEqual(existing.__context, context)
|
||||
) {
|
||||
dset(tree, baseKeys, [existing])
|
||||
keys.unshift(1)
|
||||
dset(tree, [...baseKeys, '__info'], [existing])
|
||||
index.push(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (classNames[i].__rule) {
|
||||
dset(tree, [...baseKeys, ...index, '__rule'], true)
|
||||
dset(tree, [...baseKeys, ...index, '__source'], group.source)
|
||||
|
||||
dsetEach(tree, [...baseKeys, ...index], decls)
|
||||
}
|
||||
dset(tree, [...baseKeys, ...index, '__pseudo'], classNames[i].__pseudo)
|
||||
dset(tree, [...baseKeys, ...index, '__scope'], classNames[i].scope)
|
||||
dset(tree, [...baseKeys, '__info', ...index, '__rule'], true)
|
||||
dset(
|
||||
tree,
|
||||
[...baseKeys, ...index, '__context'],
|
||||
[...baseKeys, '__info', ...index, '__source'],
|
||||
group.source
|
||||
)
|
||||
|
||||
dsetEach(tree, [...baseKeys, '__info', ...index], decls)
|
||||
}
|
||||
dset(
|
||||
tree,
|
||||
[...baseKeys, '__info', ...index, '__pseudo'],
|
||||
classNames[i].__pseudo
|
||||
)
|
||||
dset(
|
||||
tree,
|
||||
[...baseKeys, '__info', ...index, '__scope'],
|
||||
classNames[i].scope
|
||||
)
|
||||
dset(
|
||||
tree,
|
||||
[...baseKeys, '__info', ...index, '__context'],
|
||||
context.concat([]).reverse()
|
||||
)
|
||||
|
||||
// common context
|
||||
context.push(...classNames[i].__pseudo)
|
||||
context.push(...classNames[i].__pseudo.map((x) => `&${x}`))
|
||||
|
||||
for (let i = 0; i < contextKeys.length; i++) {
|
||||
if (typeof commonContext[contextKeys[i]] === 'undefined') {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "tailwindcss-language-service",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"dependencies": {
|
||||
"@ctrl/tinycolor": "^3.1.4",
|
||||
"@types/moo": "^0.5.3",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "tailwindcss-language-service",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"files": [
|
||||
|
|
|
@ -57,7 +57,10 @@ function completionsFromClassList(
|
|||
for (let i = parts.length - 1; i > 0; i--) {
|
||||
let keys = parts.slice(0, i).filter(Boolean)
|
||||
subset = dlv(state.classNames.classNames, keys)
|
||||
if (typeof subset !== 'undefined' && typeof subset.__rule === 'undefined') {
|
||||
if (
|
||||
typeof subset !== 'undefined' &&
|
||||
typeof dlv(subset, ['__info', '__rule']) === 'undefined'
|
||||
) {
|
||||
isSubset = true
|
||||
subsetKey = keys
|
||||
replacementRange = {
|
||||
|
@ -74,21 +77,45 @@ function completionsFromClassList(
|
|||
}
|
||||
}
|
||||
|
||||
// console.log(Object.keys(isSubset ? subset : state.classNames.classNames))
|
||||
|
||||
return {
|
||||
isIncomplete: false,
|
||||
items: Object.keys(isSubset ? subset : state.classNames.classNames)
|
||||
.filter((k) => k !== '__info')
|
||||
.filter((className) => isContextItem(state, [...subsetKey, className]))
|
||||
.map(
|
||||
(className, index): CompletionItem => {
|
||||
return {
|
||||
label: className + sep,
|
||||
kind: 9,
|
||||
documentation: null,
|
||||
command: {
|
||||
title: '',
|
||||
command: 'editor.action.triggerSuggest',
|
||||
},
|
||||
sortText: '-' + naturalExpand(index),
|
||||
data: [...subsetKey, className],
|
||||
textEdit: {
|
||||
newText: className + sep,
|
||||
range: replacementRange,
|
||||
},
|
||||
}
|
||||
}
|
||||
)
|
||||
.concat(
|
||||
Object.keys(isSubset ? subset : state.classNames.classNames)
|
||||
.filter((className) =>
|
||||
dlv(state.classNames.classNames, [
|
||||
...subsetKey,
|
||||
className,
|
||||
'__info',
|
||||
])
|
||||
)
|
||||
.map((className, index) => {
|
||||
let label = className
|
||||
let kind: CompletionItemKind = 21
|
||||
let documentation: string = null
|
||||
let command: any
|
||||
let sortText = naturalExpand(index)
|
||||
if (isContextItem(state, [...subsetKey, className])) {
|
||||
kind = 9
|
||||
command = { title: '', command: 'editor.action.triggerSuggest' }
|
||||
label += sep
|
||||
sortText = '-' + sortText // move to top
|
||||
} else {
|
||||
|
||||
const color = getColor(state, [className])
|
||||
if (color !== null) {
|
||||
kind = 16
|
||||
|
@ -96,28 +123,29 @@ function completionsFromClassList(
|
|||
documentation = color.toRgbString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const item = {
|
||||
label,
|
||||
return {
|
||||
label: className,
|
||||
kind,
|
||||
documentation,
|
||||
command,
|
||||
sortText,
|
||||
sortText: naturalExpand(index),
|
||||
data: [...subsetKey, className],
|
||||
textEdit: {
|
||||
newText: label,
|
||||
newText: className,
|
||||
range: replacementRange,
|
||||
},
|
||||
}
|
||||
|
||||
if (filter && !filter(item)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return item
|
||||
})
|
||||
.filter((item) => item !== null),
|
||||
)
|
||||
.filter((item) => {
|
||||
if (item === null) {
|
||||
return false
|
||||
}
|
||||
if (filter && !filter(item)) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,7 +227,10 @@ function provideAtApplyCompletions(
|
|||
},
|
||||
(item) => {
|
||||
if (item.kind === 9) {
|
||||
return semver.gte(state.version, '2.0.0-alpha.1') || flagEnabled(state, 'applyComplexClasses')
|
||||
return (
|
||||
semver.gte(state.version, '2.0.0-alpha.1') ||
|
||||
flagEnabled(state, 'applyComplexClasses')
|
||||
)
|
||||
}
|
||||
let validated = validateApply(state, item.data)
|
||||
return validated !== null && validated.isApplyable === true
|
||||
|
@ -708,8 +739,8 @@ export function resolveCompletionItem(
|
|||
return item
|
||||
}
|
||||
|
||||
const className = dlv(state.classNames.classNames, item.data)
|
||||
if (isContextItem(state, item.data)) {
|
||||
const className = dlv(state.classNames.classNames, [...item.data, '__info'])
|
||||
if (item.kind === 9) {
|
||||
item.detail = state.classNames.context[
|
||||
item.data[item.data.length - 1]
|
||||
].join(', ')
|
||||
|
@ -729,13 +760,19 @@ export function resolveCompletionItem(
|
|||
}
|
||||
|
||||
function isContextItem(state: State, keys: string[]): boolean {
|
||||
const item = dlv(state.classNames.classNames, keys)
|
||||
return Boolean(
|
||||
isObject(item) &&
|
||||
!item.__rule &&
|
||||
!Array.isArray(item) &&
|
||||
state.classNames.context[keys[keys.length - 1]]
|
||||
)
|
||||
const item = dlv(state.classNames.classNames, [keys])
|
||||
|
||||
if (!isObject(item)) {
|
||||
return false
|
||||
}
|
||||
if (!state.classNames.context[keys[keys.length - 1]]) {
|
||||
return false
|
||||
}
|
||||
if (Object.keys(item).filter((x) => x !== '__info').length > 0) {
|
||||
return true
|
||||
}
|
||||
|
||||
return isObject(item.__info) && !item.__info.__rule
|
||||
}
|
||||
|
||||
function stringifyDecls(obj: any): string {
|
||||
|
|
|
@ -89,13 +89,17 @@ function provideClassNameHover(
|
|||
}
|
||||
}
|
||||
|
||||
const css = stringifyCss(
|
||||
className.className,
|
||||
dlv(state.classNames.classNames, [...parts, '__info'])
|
||||
)
|
||||
|
||||
if (!css) return null
|
||||
|
||||
return {
|
||||
contents: {
|
||||
language: 'css',
|
||||
value: stringifyCss(
|
||||
className.className,
|
||||
dlv(state.classNames.classNames, parts)
|
||||
),
|
||||
value: css,
|
||||
},
|
||||
range: className.range,
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ export function getColor(
|
|||
state: State,
|
||||
keys: string[]
|
||||
): TinyColor | string | null {
|
||||
const item = dlv(state.classNames.classNames, keys)
|
||||
const item = dlv(state.classNames.classNames, [...keys, '__info'])
|
||||
if (!item.__rule) return null
|
||||
const props = Object.keys(removeMeta(item))
|
||||
if (props.length === 0) return null
|
||||
|
|
|
@ -8,8 +8,9 @@ export function getClassNameParts(state: State, className: string): string[] {
|
|||
let parts: string[] = className.split(separator)
|
||||
|
||||
if (parts.length === 1) {
|
||||
return dlv(state.classNames.classNames, [className, '__rule']) === true ||
|
||||
Array.isArray(dlv(state.classNames.classNames, [className]))
|
||||
return dlv(state.classNames.classNames, [className, '__info', '__rule']) ===
|
||||
true ||
|
||||
Array.isArray(dlv(state.classNames.classNames, [className, '__info']))
|
||||
? [className]
|
||||
: null
|
||||
}
|
||||
|
@ -34,8 +35,8 @@ export function getClassNameParts(state: State, className: string): string[] {
|
|||
|
||||
return possibilities.find((key) => {
|
||||
if (
|
||||
dlv(state.classNames.classNames, [...key, '__rule']) === true ||
|
||||
Array.isArray(dlv(state.classNames.classNames, [...key]))
|
||||
dlv(state.classNames.classNames, [...key, '__info', '__rule']) === true ||
|
||||
Array.isArray(dlv(state.classNames.classNames, [...key, '__info']))
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ export function getClassNameDecls(
|
|||
const parts = getClassNameParts(state, className)
|
||||
if (!parts) return null
|
||||
|
||||
const info = dlv(state.classNames.classNames, parts)
|
||||
const info = dlv(state.classNames.classNames, [...parts, '__info'])
|
||||
|
||||
if (Array.isArray(info)) {
|
||||
return info.map(removeMeta)
|
||||
|
|
|
@ -10,7 +10,7 @@ export function getClassNameMeta(
|
|||
? classNameOrParts
|
||||
: getClassNameParts(state, classNameOrParts)
|
||||
if (!parts) return null
|
||||
const info = dlv(state.classNames.classNames, parts)
|
||||
const info = dlv(state.classNames.classNames, [...parts, '__info'])
|
||||
|
||||
if (Array.isArray(info)) {
|
||||
return info.map((i) => ({
|
||||
|
|
Loading…
Reference in New Issue