1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
diff --git a/packages/tailwindcss-language-service/src/completionProvider.ts b/packages/tailwindcss-language-service/src/completionProvider.ts
index 103dba9ccf59d1827e58e5167beb03b236469b86..127d9ca8cdde9517692bd36642333a7449258d7c 100644
--- a/packages/tailwindcss-language-service/src/completionProvider.ts
+++ b/packages/tailwindcss-language-service/src/completionProvider.ts
@@ -7,6 +7,7 @@ MarkupKind,
CompletionList,
TextDocument,
Position,
+ CompletionContext,
} from 'vscode-languageserver'
const dlv = require('dlv')
import removeMeta from './util/removeMeta'
@@ -43,7 +44,8 @@ state: State,
classList: string,
classListRange: Range,
filter?: (item: CompletionItem) => boolean,
- document?: TextDocument
+ document?: TextDocument,
+ context?: CompletionContext
): CompletionList {
let classNames = classList.split(/[\s+]/)
const partialClassName = classNames[classNames.length - 1]
@@ -62,6 +64,58 @@ },
}
if (state.jit) {
+ if (
+ context &&
+ (context.triggerKind === 1 ||
+ (context.triggerKind === 2 && context.triggerCharacter === '/')) &&
+ partialClassName.includes('/')
+ ) {
+ let beforeSlash = partialClassName.split('/').slice(0, -1).join('/')
+ let testClass = beforeSlash + '/[0]'
+ let { rules } = jit.generateRules(state, [testClass])
+ if (rules.length > 0) {
+ let opacities = dlv(state.config, 'theme.opacity', {})
+ if (!isObject(opacities)) {
+ opacities = {}
+ }
+ return {
+ isIncomplete: false,
+ items: Object.keys(opacities).map((opacity, index) => {
+ let className = `${beforeSlash}/${opacity}`
+ let kind: CompletionItemKind = 21
+ let documentation: string = null
+
+ const color = getColor(state, className)
+ if (color !== null) {
+ kind = 16
+ if (typeof color !== 'string') {
+ documentation = color.toRgbString().replace(/(^rgba\([^)]+) 0\)$/, '$1 0.001)')
+ }
+ }
+
+ return {
+ label: opacity,
+ detail: stringifyConfigValue(opacities[opacity]),
+ documentation,
+ kind,
+ sortText: naturalExpand(index),
+ data: [className],
+ textEdit: {
+ newText: opacity,
+ range: {
+ ...replacementRange,
+ start: {
+ ...replacementRange.start,
+ character: replacementRange.start.character + beforeSlash.length + 1,
+ },
+ },
+ },
+ }
+ }),
+ }
+ }
+ }
+
let allVariants = Object.keys(state.variants)
let { variants: existingVariants, offset } = getVariantsFromClassName(state, partialClassName)
@@ -256,7 +310,8 @@
function provideClassAttributeCompletions(
state: State,
document: TextDocument,
- position: Position
+ position: Position,
+ context?: CompletionContext
): CompletionList {
let str = document.getText({
start: { line: Math.max(position.line - 10, 0), character: 0 },
@@ -299,7 +354,8 @@ },
end: position,
},
undefined,
- document
+ document,
+ context
)
}
} catch (_) {}
@@ -417,10 +473,11 @@
function provideClassNameCompletions(
state: State,
document: TextDocument,
- position: Position
+ position: Position,
+ context?: CompletionContext
): CompletionList {
if (isHtmlContext(state, document, position) || isJsContext(state, document, position)) {
- return provideClassAttributeCompletions(state, document, position)
+ return provideClassAttributeCompletions(state, document, position, context)
}
if (isCssContext(state, document, position)) {
@@ -925,11 +982,16 @@ end: position,
})
}
-export async function doComplete(state: State, document: TextDocument, position: Position) {
+export async function doComplete(
+ state: State,
+ document: TextDocument,
+ position: Position,
+ context?: CompletionContext
+) {
if (state === null) return { items: [], isIncomplete: false }
const result =
- provideClassNameCompletions(state, document, position) ||
+ provideClassNameCompletions(state, document, position, context) ||
provideCssHelperCompletions(state, document, position) ||
provideCssDirectiveCompletions(state, document, position) ||
provideScreenDirectiveCompletions(state, document, position) ||
@@ -958,8 +1020,13 @@ item.detail = stringifyScreen(screens[item.label] as Screen)
return item
}
+ if (!Array.isArray(item.data)) {
+ return item
+ }
+
if (state.jit) {
if (item.kind === 9) return item
+ if (item.detail && item.documentation) return item
let { root, rules } = jit.generateRules(state, [item.data.join(state.separator)])
if (rules.length === 0) return item
if (!item.detail) {
|