Skip to content

Commit 491a48d

Browse files
committed
Merge branch 'master' into restructure-explorer
2 parents f2fa26f + 93ddfe8 commit 491a48d

File tree

16 files changed

+430
-74
lines changed

16 files changed

+430
-74
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ Enable completions when using [Emmet](https://emmet.io/)-style syntax, for examp
5656
}
5757
```
5858

59+
### `tailwindCSS.colorDecorators`
60+
61+
Controls whether the editor should render inline color decorators for Tailwind CSS classes and helper functions.
62+
63+
- `inherit`: Color decorators are rendered if `editor.colorDecorators` is enabled.
64+
- `on`: Color decorators are rendered.
65+
- `off`: Color decorators are not rendered.
66+
5967
### `tailwindCSS.validate`
6068

6169
Enable linting. Rules can be configured individually using the `tailwindcss.lint` settings:

package-lock.json

Lines changed: 13 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"preview": true,
66
"author": "Brad Cornes <hello@bradley.dev>",
77
"license": "MIT",
8-
"version": "0.4.1",
8+
"version": "0.4.3",
99
"homepage": "https://github.com/tailwindcss/intellisense",
1010
"bugs": {
1111
"url": "https://github.com/tailwindcss/intellisense/issues",
@@ -71,6 +71,22 @@
7171
"default": {},
7272
"markdownDescription": "Enable features in languages that are not supported by default. Add a mapping here between the new language and an already supported language.\n E.g.: `{\"plaintext\": \"html\"}`"
7373
},
74+
"tailwindCSS.colorDecorators": {
75+
"type": "string",
76+
"enum": [
77+
"inherit",
78+
"on",
79+
"off"
80+
],
81+
"markdownEnumDescriptions": [
82+
"Color decorators are rendered if `editor.colorDecorators` is enabled.",
83+
"Color decorators are rendered.",
84+
"Color decorators are not rendered."
85+
],
86+
"default": "inherit",
87+
"markdownDescription": "Controls whether the editor should render inline color decorators for Tailwind CSS classes and helper functions.",
88+
"scope": "language-overridable"
89+
},
7490
"tailwindCSS.validate": {
7591
"type": "boolean",
7692
"default": true,
@@ -209,6 +225,7 @@
209225
"@babel/core": "^7.9.6",
210226
"@babel/register": "^7.9.0",
211227
"@ctrl/tinycolor": "^3.1.0",
228+
"@types/debounce": "^1.2.0",
212229
"@types/mocha": "^5.2.0",
213230
"@types/moo": "^0.5.3",
214231
"@types/node": "^13.9.3",
@@ -218,6 +235,7 @@
218235
"chokidar": "^3.3.1",
219236
"concurrently": "^5.1.0",
220237
"css.escape": "^1.5.1",
238+
"debounce": "^1.2.0",
221239
"detect-indent": "^6.0.0",
222240
"dlv": "^1.1.3",
223241
"dset": "^2.0.1",

src/class-names/index.js

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,12 @@ import invariant from 'tiny-invariant'
1010
import getPlugins from './getPlugins'
1111
import getVariants from './getVariants'
1212
import resolveConfig from './resolveConfig'
13-
import * as util from 'util'
1413
import * as path from 'path'
1514
import * as fs from 'fs'
1615
import { getUtilityConfigMap } from './getUtilityConfigMap'
1716
import glob from 'fast-glob'
1817
import normalizePath from 'normalize-path'
1918

20-
function TailwindConfigError(error) {
21-
Error.call(this)
22-
Error.captureStackTrace(this, this.constructor)
23-
24-
this.name = this.constructor.name
25-
this.message = error.message
26-
this.stack = error.stack
27-
}
28-
29-
util.inherits(TailwindConfigError, Error)
30-
3119
function arraysEqual(arr1, arr2) {
3220
return (
3321
JSON.stringify(arr1.concat([]).sort()) ===
@@ -47,6 +35,7 @@ export default async function getClassNames(
4735
let tailwindcss
4836
let browserslistModule
4937
let version
38+
let featureFlags = { future: [], experimental: [] }
5039

5140
const configPaths = (
5241
await glob(CONFIG_GLOB, {
@@ -75,6 +64,10 @@ export default async function getClassNames(
7564
browserslistModule = importFrom(tailwindBase, 'browserslist')
7665
} catch (_) {}
7766

67+
try {
68+
featureFlags = importFrom(tailwindBase, './lib/featureFlags.js').default
69+
} catch (_) {}
70+
7871
const sepLocation = semver.gte(version, '0.99.0')
7972
? ['separator']
8073
: ['options', 'separator']
@@ -93,23 +86,34 @@ export default async function getClassNames(
9386
try {
9487
config = __non_webpack_require__(configPath)
9588
} catch (error) {
96-
throw new TailwindConfigError(error)
89+
hook.unwatch()
90+
hook.unhook()
91+
throw error
9792
}
93+
9894
hook.unwatch()
9995

100-
const [base, components, utilities] = await Promise.all(
101-
[
102-
semver.gte(version, '0.99.0') ? 'base' : 'preflight',
103-
'components',
104-
'utilities',
105-
].map((group) =>
106-
postcss([tailwindcss(configPath)]).process(`@tailwind ${group};`, {
107-
from: undefined,
108-
})
96+
let postcssResult
97+
98+
try {
99+
postcssResult = await Promise.all(
100+
[
101+
semver.gte(version, '0.99.0') ? 'base' : 'preflight',
102+
'components',
103+
'utilities',
104+
].map((group) =>
105+
postcss([tailwindcss(configPath)]).process(`@tailwind ${group};`, {
106+
from: undefined,
107+
})
108+
)
109109
)
110-
)
110+
} catch (error) {
111+
throw error
112+
} finally {
113+
hook.unhook()
114+
}
111115

112-
hook.unhook()
116+
const [base, components, utilities] = postcssResult
113117

114118
if (typeof userSeperator !== 'undefined') {
115119
dset(config, sepLocation, userSeperator)
@@ -152,6 +156,7 @@ export default async function getClassNames(
152156
tailwindcss,
153157
postcss,
154158
},
159+
featureFlags,
155160
}
156161
}
157162

@@ -174,12 +179,7 @@ export default async function getClassNames(
174179
try {
175180
result = await run()
176181
} catch (error) {
177-
if (error instanceof TailwindConfigError) {
178-
onChange({ error })
179-
} else {
180-
unwatch()
181-
onChange(null)
182-
}
182+
onChange({ error })
183183
return
184184
}
185185
const newDeps = [result.configPath, ...result.dependencies]

src/extension.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { dedupe, equal } from './util/array'
2525
import { registerConfigExplorer, ConfigExplorerApi } from './lib/configExplorer'
2626
import { createEmitter } from './lib/emitter'
2727
import { onMessage } from './lsp/notifications'
28+
import { registerColorDecorator } from './lib/registerColorDecorator'
2829

2930
const CLIENT_ID = 'tailwindcss-intellisense'
3031
const CLIENT_NAME = 'Tailwind CSS IntelliSense'
@@ -159,6 +160,7 @@ export function activate(context: ExtensionContext) {
159160
}
160161
explorer.addWorkspace({ client, emitter })
161162
registerConfigErrorHandler(emitter)
163+
registerColorDecorator(client, context, emitter)
162164
onMessage(client, 'getConfiguration', async (scope) => {
163165
return Workspace.getConfiguration('tailwindCSS', scope)
164166
})

src/lib/registerColorDecorator.ts

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import { window, workspace, ExtensionContext, TextEditor } from 'vscode'
2+
import { NotificationEmitter } from './emitter'
3+
import { LanguageClient } from 'vscode-languageclient'
4+
import debounce from 'debounce'
5+
6+
const colorDecorationType = window.createTextEditorDecorationType({
7+
before: {
8+
width: '0.8em',
9+
height: '0.8em',
10+
contentText: ' ',
11+
border: '0.1em solid',
12+
margin: '0.1em 0.2em 0',
13+
},
14+
dark: {
15+
before: {
16+
borderColor: '#eeeeee',
17+
},
18+
},
19+
light: {
20+
before: {
21+
borderColor: '#000000',
22+
},
23+
},
24+
})
25+
26+
export function registerColorDecorator(
27+
client: LanguageClient,
28+
context: ExtensionContext,
29+
emitter: NotificationEmitter
30+
) {
31+
let activeEditor = window.activeTextEditor
32+
33+
async function updateDecorations() {
34+
return updateDecorationsInEditor(activeEditor)
35+
}
36+
37+
async function updateDecorationsInEditor(editor: TextEditor) {
38+
if (!editor) return
39+
if (editor.document.uri.scheme !== 'file') return
40+
41+
let workspaceFolder = workspace.getWorkspaceFolder(editor.document.uri)
42+
if (
43+
!workspaceFolder ||
44+
workspaceFolder.uri.toString() !==
45+
client.clientOptions.workspaceFolder.uri.toString()
46+
) {
47+
return
48+
}
49+
50+
let preference =
51+
workspace.getConfiguration('tailwindCSS', editor.document)
52+
.colorDecorators || 'inherit'
53+
54+
let enabled: boolean =
55+
preference === 'inherit'
56+
? Boolean(workspace.getConfiguration('editor').colorDecorators)
57+
: preference === 'on'
58+
59+
if (!enabled) {
60+
editor.setDecorations(colorDecorationType, [])
61+
return
62+
}
63+
64+
let { colors } = await emitter.emit('getDocumentColors', {
65+
document: editor.document.uri.toString(),
66+
})
67+
68+
editor.setDecorations(
69+
colorDecorationType,
70+
colors
71+
.filter(({ color }) => color !== 'rgba(0, 0, 0, 0.01)')
72+
.map(({ range, color }) => ({
73+
range,
74+
renderOptions: { before: { backgroundColor: color } },
75+
}))
76+
)
77+
}
78+
79+
const triggerUpdateDecorations = debounce(updateDecorations, 200)
80+
81+
if (activeEditor) {
82+
triggerUpdateDecorations()
83+
}
84+
85+
window.onDidChangeActiveTextEditor(
86+
(editor) => {
87+
activeEditor = editor
88+
if (editor) {
89+
triggerUpdateDecorations()
90+
}
91+
},
92+
null,
93+
context.subscriptions
94+
)
95+
96+
workspace.onDidChangeTextDocument(
97+
(event) => {
98+
if (activeEditor && event.document === activeEditor.document) {
99+
triggerUpdateDecorations()
100+
}
101+
},
102+
null,
103+
context.subscriptions
104+
)
105+
106+
workspace.onDidOpenTextDocument(
107+
(document) => {
108+
if (activeEditor && document === activeEditor.document) {
109+
triggerUpdateDecorations()
110+
}
111+
},
112+
null,
113+
context.subscriptions
114+
)
115+
116+
workspace.onDidChangeConfiguration((e) => {
117+
if (
118+
e.affectsConfiguration('editor.colorDecorators') ||
119+
e.affectsConfiguration('tailwindCSS.colorDecorators')
120+
) {
121+
window.visibleTextEditors.forEach(updateDecorationsInEditor)
122+
}
123+
})
124+
125+
emitter.on('configUpdated', () => {
126+
window.visibleTextEditors.forEach(updateDecorationsInEditor)
127+
})
128+
129+
emitter.on('configError', () => {
130+
window.visibleTextEditors.forEach(updateDecorationsInEditor)
131+
})
132+
}

0 commit comments

Comments
 (0)