Skip to content

Commit 6ac1d27

Browse files
committed
fix: autodetect if twind project, twind output channel, restart command
1 parent 94ff4e1 commit 6ac1d27

File tree

5 files changed

+195
-55
lines changed

5 files changed

+195
-55
lines changed

CHANGELOG.md

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
11
# Change Log
22

3-
All notable changes to the "vscode-twind-intellisense" extension will be documented in this file.
4-
5-
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
6-
7-
## [0.0.2]
8-
9-
- Initial release
3+
See [the releases page](https://github.com/tw-in-js/vscode-twind-intellisense/releases).

README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -173,13 +173,17 @@ You can enable IntelliSense for other `style` like functions by configuring `twi
173173

174174
Allows to enabling/disabling additional debug information shown in hover and completion popups (default: `false`) by configuring `twind.debug`.
175175

176+
### Enable
177+
178+
Allows to enabling/disabling the extension (default: `true`).
179+
176180
## Features
177181

178182
Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file.
179183

180184
## Release Notes
181185

182-
See [the changelog](https://github.com/tw-in-js/vscode-twind-intellisense/blob/main/CHANGELOG.md).
186+
See [the releases page](https://github.com/tw-in-js/vscode-twind-intellisense/releases).
183187

184188
## For more information
185189

package.json

+39-19
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,31 @@
3131
"Linters",
3232
"Other"
3333
],
34+
"extensionDependencies": [
35+
"vscode.typescript-language-features"
36+
],
37+
"extensionKind": [
38+
"workspace",
39+
"ui"
40+
],
3441
"activationEvents": [
35-
"workspaceContains:**/config/twind.config.ts",
36-
"workspaceContains:**/config/twind.config.js",
37-
"workspaceContains:**/config/twind.config.mjs",
38-
"workspaceContains:**/config/twind.config.cjs",
39-
"workspaceContains:**/src/twind.config.ts",
40-
"workspaceContains:**/src/twind.config.js",
41-
"workspaceContains:**/src/twind.config.mjs",
42-
"workspaceContains:**/src/twind.config.cjs",
43-
"workspaceContains:**/public/twind.config.ts",
44-
"workspaceContains:**/public/twind.config.js",
45-
"workspaceContains:**/public/twind.config.mjs",
46-
"workspaceContains:**/public/twind.config.cjs",
47-
"workspaceContains:**/twind.config.ts",
48-
"workspaceContains:**/twind.config.js",
49-
"workspaceContains:**/twind.config.mjs",
50-
"workspaceContains:**/twind.config.cjs",
42+
"onCommand:twind.restart",
43+
"workspaceContains:config/twind.config.ts",
44+
"workspaceContains:config/twind.config.js",
45+
"workspaceContains:config/twind.config.mjs",
46+
"workspaceContains:config/twind.config.cjs",
47+
"workspaceContains:src/twind.config.ts",
48+
"workspaceContains:src/twind.config.js",
49+
"workspaceContains:src/twind.config.mjs",
50+
"workspaceContains:src/twind.config.cjs",
51+
"workspaceContains:public/twind.config.ts",
52+
"workspaceContains:public/twind.config.js",
53+
"workspaceContains:public/twind.config.mjs",
54+
"workspaceContains:public/twind.config.cjs",
55+
"workspaceContains:twind.config.ts",
56+
"workspaceContains:twind.config.js",
57+
"workspaceContains:twind.config.mjs",
58+
"workspaceContains:twind.config.cjs",
5159
"onLanguage:javascript",
5260
"onLanguage:javascriptreact",
5361
"onLanguage:typescript",
@@ -60,6 +68,12 @@
6068
"enableForWorkspaceTypeScriptVersions": true
6169
}
6270
],
71+
"commands": [
72+
{
73+
"command": "twind.restart",
74+
"title": "Twind: Restart IntelliSense"
75+
}
76+
],
6377
"configuration": [
6478
{
6579
"id": "twind",
@@ -106,21 +120,27 @@
106120
"type": "boolean",
107121
"description": "Enable/disable additional debug information.",
108122
"default": false
123+
},
124+
"twind.enable": {
125+
"type": "boolean",
126+
"default": true,
127+
"markdownDescription": "Controls whether Twind intellisense is enabled or not."
109128
}
110129
}
111130
}
112131
]
113132
},
114133
"dependencies": {
115-
"@twind/typescript-plugin": "0.3.1"
134+
"@twind/typescript-plugin": "^0.3.2"
116135
},
117136
"main": "./out/extension.js",
118137
"scripts": {
119138
"vscode:prepublish": "yarn run build",
120-
"build": "esbuild src/extension.ts --outdir=out --bundle --minify --format=cjs --platform=node --sourcemap=external --target=es2018 --external:vscode",
139+
"build": "esbuild src/extension.ts --outdir=out --bundle --format=cjs --platform=node --sourcemap=external --target=es2018 --external:vscode",
121140
"watch": "yarn run build --watch",
122141
"pretest": "yarn run build && yarn run lint",
123-
"test": "node ./out/test/run.js"
142+
"release": "npx np",
143+
"version": "npx vsce package"
124144
},
125145
"devDependencies": {
126146
"@types/node": "^12.11.7",

src/extension.ts

+135-19
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,157 @@ const typeScriptExtensionId = 'vscode.typescript-language-features'
55
const pluginId = '@twind/typescript-plugin'
66
const configurationSection = 'twind'
77

8+
// the application insights key (also known as instrumentation key)
9+
const extensionName = process.env.EXTENSION_NAME || 'dev.twind-intellisense'
10+
const extensionVersion = process.env.EXTENSION_VERSION || '0.0.0'
11+
812
interface SynchronizedConfiguration {
913
tags: ReadonlyArray<string>
1014
attributes: ReadonlyArray<string>
1115
styles: ReadonlyArray<string>
1216
debug: boolean
17+
enable: boolean
1318
// Readonly validate: boolean;
1419
// readonly lint: { [key: string]: any };
1520
// readonly emmet: { [key: string]: any };
1621
}
1722

23+
type Logger = (message: string) => void
24+
25+
interface State {
26+
hasTwind?: boolean
27+
}
28+
1829
export async function activate(context: vscode.ExtensionContext) {
30+
const log = createLogger(vscode.window.createOutputChannel('Twind IntelliSense'))
31+
log(`Extension Name: ${extensionName}.`)
32+
log(`Extension Version: ${extensionVersion}.`)
33+
34+
await enableExtension(context, log).catch((error) => {
35+
log(`Activating ${pluginId} failed: ${error.stack}`)
36+
})
37+
}
38+
39+
async function enableExtension(context: vscode.ExtensionContext, log: Logger) {
40+
const state: State = { hasTwind: undefined }
41+
42+
const update = async () => {
43+
const localTwindManifestFiles = await vscode.workspace.findFiles(
44+
'**/node_modules/twind/package.json',
45+
null,
46+
1,
47+
)
48+
49+
const twindConfigFiles = localTwindManifestFiles.length
50+
? []
51+
: await vscode.workspace.findFiles('**/twind.config.{ts,js,mjs,cjs}', '**/node_modules/**', 1)
52+
53+
let hasTwind = false
54+
if (localTwindManifestFiles.length) {
55+
log(`Using local twind`)
56+
hasTwind = true
57+
} else if (twindConfigFiles.length) {
58+
log(`Using builtin twind`)
59+
hasTwind = true
60+
} else {
61+
log(`No twind package and no twind config file found. Not activating Twind IntelliSense.`)
62+
hasTwind = false
63+
}
64+
65+
if (hasTwind !== state.hasTwind) {
66+
state.hasTwind = hasTwind
67+
synchronizeConfiguration(api, state, log)
68+
}
69+
}
70+
71+
const api = await activateTypescriptPlugin(log)
72+
73+
const listener = () => {
74+
update().catch((error) => {
75+
log(error.stacktrace)
76+
})
77+
}
78+
79+
context.subscriptions.push(
80+
vscode.commands.registerCommand('twind.restart', () => {
81+
state.hasTwind = undefined
82+
listener()
83+
}),
84+
)
85+
86+
const twindWatcher = vscode.workspace.createFileSystemWatcher(
87+
'**/node_modules/twind/package.json',
88+
)
89+
90+
context.subscriptions.push(twindWatcher)
91+
context.subscriptions.push(twindWatcher.onDidCreate(listener))
92+
context.subscriptions.push(twindWatcher.onDidChange(listener))
93+
context.subscriptions.push(twindWatcher.onDidDelete(listener))
94+
95+
const configWatcher = vscode.workspace.createFileSystemWatcher('**/twind.config.{ts,js,mjs,cjs}')
96+
97+
context.subscriptions.push(configWatcher)
98+
context.subscriptions.push(configWatcher.onDidCreate(listener))
99+
context.subscriptions.push(configWatcher.onDidDelete(listener))
100+
101+
const packageWatcher = vscode.workspace.createFileSystemWatcher(
102+
'**/{package,package-lock.json,yarn.lock,pnpm-lock.yaml}',
103+
)
104+
105+
context.subscriptions.push(packageWatcher)
106+
context.subscriptions.push(packageWatcher.onDidCreate(listener))
107+
context.subscriptions.push(packageWatcher.onDidCreate(listener))
108+
context.subscriptions.push(packageWatcher.onDidDelete(listener))
109+
110+
await update()
111+
}
112+
113+
async function activateTypescriptPlugin(log: Logger) {
19114
const extension = vscode.extensions.getExtension(typeScriptExtensionId)
20115
if (!extension) {
116+
log(`Extension ${typeScriptExtensionId} not found. No IntelliSense will be provided.`)
21117
return
22118
}
23119

24120
await extension.activate()
25-
if (!extension.exports || !extension.exports.getAPI) {
26-
return
27-
}
28-
const api = extension.exports.getAPI(0)
121+
122+
const api = extension.exports?.getAPI?.(0)
123+
29124
if (!api) {
125+
log(
126+
`Extension ${typeScriptExtensionId} did not export an API. No IntelliSense will be provided.`,
127+
)
30128
return
31129
}
32130

33-
vscode.workspace.onDidChangeConfiguration(
34-
(e) => {
35-
if (e.affectsConfiguration(configurationSection)) {
36-
synchronizeConfiguration(api)
37-
}
38-
},
39-
undefined,
40-
context.subscriptions,
41-
)
131+
return api
132+
}
42133

43-
synchronizeConfiguration(api)
134+
function createLogger(outputChannel: vscode.OutputChannel): Logger {
135+
return (message) => {
136+
const title = new Date().toLocaleTimeString()
137+
outputChannel.appendLine(`[${title}] ${message}`)
138+
}
44139
}
45140

46-
function synchronizeConfiguration(api: any) {
47-
api.configurePlugin(pluginId, getConfiguration())
141+
function synchronizeConfiguration(api: any, state: State, log: Logger) {
142+
const config = getConfiguration()
143+
144+
if (config.enable) {
145+
log('Extension is enabled. To disable, change the `twind.enable` setting to `false`.')
146+
147+
if (state.hasTwind) {
148+
log(`Configuring ${pluginId} using: ${JSON.stringify(config, null, 2)}`)
149+
} else {
150+
config.enable = false
151+
}
152+
} else {
153+
log(
154+
'Extension is disabled. No IntelliSense will be provided. To enable, change the `twind.enable` setting to `true`.',
155+
)
156+
}
157+
158+
api.configurePlugin(pluginId, config)
48159
}
49160

50161
function getConfiguration(): SynchronizedConfiguration {
@@ -54,24 +165,29 @@ function getConfiguration(): SynchronizedConfiguration {
54165
attributes: ['tw', 'class', 'className'],
55166
styles: ['style', 'styled'],
56167
debug: false,
168+
enable: true,
57169
}
58170

59171
withConfigValue<string[]>(config, 'tags', (tags) => {
60172
outConfig.tags = tags
61173
})
62174

63-
withConfigValue<string[]>(config, 'attributes', (attributes) => {
175+
withConfigValue<string[]>(config, 'attributes', (attributes) => {
64176
outConfig.attributes = attributes
65177
})
66178

67-
withConfigValue<string[]>(config, 'styles', (styles) => {
179+
withConfigValue<string[]>(config, 'styles', (styles) => {
68180
outConfig.styles = styles
69181
})
70182

71-
withConfigValue<boolean>(config, 'debug', (debug) => {
183+
withConfigValue<boolean>(config, 'debug', (debug) => {
72184
outConfig.debug = debug
73185
})
74186

187+
withConfigValue<boolean>(config, 'enable', (enable) => {
188+
outConfig.enable = enable
189+
})
190+
75191
return outConfig
76192
}
77193

yarn.lock

+15-9
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,16 @@
1414
resolved "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
1515
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
1616

17-
"@twind/[email protected].1":
18-
version "0.3.1"
19-
resolved "https://registry.npmjs.org/@twind/typescript-plugin/-/typescript-plugin-0.3.1.tgz#94a841bafc838a553f796999ac329aba605f6478"
20-
integrity sha512-hRg8Wb7Ke+50BnrBspz+sBGJwqybqkv54e/t/6VncfsJKxeVQHjuM8BViArBzmYzyuGeriSOiF3PItcYTKbNOg==
17+
"@twind/typescript-plugin@^0.3.2":
18+
version "0.3.2"
19+
resolved "https://registry.npmjs.org/@twind/typescript-plugin/-/typescript-plugin-0.3.2.tgz#26af8ff82dcdd79c2dc59ff354cac124f2f7aaca"
20+
integrity sha512-a96A+iachKZsiFWV6xNzo0NMiV2cAnTzDO6bMYdbvTcqvXPcW9FzOGVXNeymAd7phAmQ1ruRZ4PcUV8ES7ijjA==
2121
dependencies:
2222
cssbeautify "^0.3.1"
2323
esbuild "^0.9.3"
24+
fast-json-stable-stringify "^2.1.0"
2425
match-sorter "^6.3.0"
25-
twind "^0.16.6"
26+
twind "^0.16.8"
2627
typescript "^4.1.0"
2728
typescript-template-language-service-decorator "^2.2.0"
2829
vscode-languageserver-types "^3.13.0"
@@ -166,6 +167,11 @@ esbuild@^0.9.3, esbuild@^0.9.6:
166167
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.9.6.tgz#2cae519e7ce2328ecf57ae738090d07ce7245850"
167168
integrity sha512-F6vASxU0wT/Davt9aj2qtDwDNSkQxh9VbyO56M7PDWD+D/Vgq/rmUDGDQo7te76W5auauVojjnQr/wTu3vpaUA==
168169

170+
fast-json-stable-stringify@^2.1.0:
171+
version "2.1.0"
172+
resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
173+
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
174+
169175
fs.realpath@^1.0.0:
170176
version "1.0.0"
171177
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -361,10 +367,10 @@ style-vendorizer@^2.0.0:
361367
resolved "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9"
362368
integrity sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=
363369

364-
twind@^0.16.6:
365-
version "0.16.7"
366-
resolved "https://registry.npmjs.org/twind/-/twind-0.16.7.tgz#1d57cbe8a63ddf6ac1d19e8595c20bb4c1a8c95c"
367-
integrity sha512-OuYft+pWBK9XjswVbVQlaVL7JXnOWj9maAqUuUEel1q8bnkjb9MOb8Vw9W+OGvMsV0T5/BrhEYf0ZDN1SDZDpg==
370+
twind@^0.16.8:
371+
version "0.16.8"
372+
resolved "https://registry.npmjs.org/twind/-/twind-0.16.8.tgz#164da6c889cb52607915bd5b97e62c969ca10cc3"
373+
integrity sha512-9mnQS/q1U+U6cRSdoE/PozGSOpENZWjS/MOFzcd4dpCZQRWoGa5DKBuTRJiHZdSO9ClEnFjlVB8dGR4w4yTimw==
368374
dependencies:
369375
csstype "^3.0.5"
370376
htmlparser2 "^6.0.0"

0 commit comments

Comments
 (0)