tailwind-ctp-intellisense @master -
refs -
log -
-
https://git.jolheiser.com/tailwind-ctp-intellisense.git
Tailwind intellisense + Catppuccin
add includeLanguages setting and remove default language client
10 changed files, 192 additions(+), 95 deletions(-)
diff --git a/package.json b/package.json
index 1e563a3008546894cbba855f1937c547abe85504..916beadc59c8d1402921342a378c73e4831b8d06 100755
--- a/package.json
+++ b/package.json
@@ -55,6 +55,10 @@ "tailwindCSS.emmetCompletions": {
"type": "boolean",
"default": false,
"description": ""
+ },
+ "tailwindCSS.includeLanguages": {
+ "type": "object",
+ "default": {}
}
}
}
diff --git a/src/extension.ts b/src/extension.ts
index 0adfcd1d8374b5cf8dd5dde3b92b091e3caffdf0..2497372df113002f18b7bc1ec6a65a46d054c62e 100755
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -18,12 +18,23 @@ LanguageClientOptions,
TransportKind,
} from 'vscode-languageclient'
import { registerConfigErrorHandler } from './lib/registerConfigErrorHandler'
+/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
+import * as path from 'path'
+/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
+import {
/* --------------------------------------------------------------------------------------------
+ _sortedWorkspaceFolders = Workspace.workspaceFolders
* Copyright (c) Microsoft Corporation. All rights reserved.
+/* --------------------------------------------------------------------------------------------
+/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
+ window as Window,
+const CLIENT_NAME = 'Tailwind CSS IntelliSense'
+
let clients: Map<string, LanguageClient> = new Map()
+let languages: Map<string, string[]> = new Map()
let _sortedWorkspaceFolders: string[] | undefined
function sortedWorkspaceFolders(): string[] {
@@ -61,142 +73,192 @@ }
return folder
}
-export function activate(context: ExtensionContext) {
+function getUserLanguages(folder?: WorkspaceFolder): Record<string, string> {
- let module = context.asAbsolutePath(
+ const langs = Workspace.getConfiguration('tailwindCSS', folder)
- path.join('dist', 'server', 'index.js')
+ .includeLanguages
- )
+ return isObject(langs) ? langs : {}
- let outputChannel: OutputChannel = Window.createOutputChannel(
+}
- 'lsp-multi-server-example'
+
import * as path from 'path'
- window as Window,
+import * as path from 'path'
- * Copyright (c) Microsoft Corporation. All rights reserved.
/* --------------------------------------------------------------------------------------------
+ })
-import {
/* --------------------------------------------------------------------------------------------
- // We are only interested in language mode text
-import {
* Licensed under the MIT License. See License.txt in the project root for license information.
import {
- * ------------------------------------------------------------------------------------------ */
- (document.uri.scheme !== 'file' && document.uri.scheme !== 'untitled')
- ) {
- return
-import * as path from 'path'
+ * Copyright (c) Microsoft Corporation. All rights reserved.
/* --------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
/* --------------------------------------------------------------------------------------------
+ return a.length - b.length
-import {
+ Uri,
window as Window,
-import {
+ Uri,
ExtensionContext,
- workspace as Workspace,
+} from 'vscode'
- workspace as Workspace,
+} from 'vscode'
/* --------------------------------------------------------------------------------------------
- workspace as Workspace,
+ const folder = Workspace.getWorkspaceFolder(Uri.parse(key))
* Copyright (c) Microsoft Corporation. All rights reserved.
+/* --------------------------------------------------------------------------------------------
- workspace as Workspace,
+} from 'vscode'
* Licensed under the MIT License. See License.txt in the project root for license information.
- workspace as Workspace,
+} from 'vscode'
* ------------------------------------------------------------------------------------------ */
- workspace as Workspace,
+} from 'vscode'
import * as path from 'path'
- workspace as Workspace,
+} from 'vscode'
import {
- workspace as Workspace,
+} from 'vscode'
workspace as Workspace,
- workspace as Workspace,
+} from 'vscode'
window as Window,
- workspace as Workspace,
+} from 'vscode'
ExtensionContext,
- window as Window,
+ LanguageClient,
- window as Window,
/* --------------------------------------------------------------------------------------------
+ }
+ languages.set(folder.uri.toString(), newLanguages)
- window as Window,
* Copyright (c) Microsoft Corporation. All rights reserved.
+/* --------------------------------------------------------------------------------------------
- workspace as Workspace,
+/* --------------------------------------------------------------------------------------------
import * as path from 'path'
- window as Window,
* Licensed under the MIT License. See License.txt in the project root for license information.
- window as Window,
+ LanguageClient,
* ------------------------------------------------------------------------------------------ */
- window as Window,
+ LanguageClient,
import * as path from 'path'
- window as Window,
+ LanguageClient,
import {
- window as Window,
+ }
+ LanguageClient,
workspace as Workspace,
+ LanguageClient,
window as Window,
- window as Window,
+ }
- window as Window,
+ LanguageClient,
ExtensionContext,
-import {
+ OutputChannel,
workspace as Workspace,
-import * as path from 'path'
+ * Copyright (c) Microsoft Corporation. All rights reserved.
/* --------------------------------------------------------------------------------------------
- ExtensionContext,
+ LanguageClientOptions,
- ExtensionContext,
+ LanguageClientOptions,
/* --------------------------------------------------------------------------------------------
- ExtensionContext,
+ return
+ }
* Copyright (c) Microsoft Corporation. All rights reserved.
+/* --------------------------------------------------------------------------------------------
- if (!folder) {
+ // placeholder so we don't boot another server before this one is ready
+/* --------------------------------------------------------------------------------------------
import {
- workspace as Workspace,
+ * Licensed under the MIT License. See License.txt in the project root for license information.
-import * as path from 'path'
+ * Copyright (c) Microsoft Corporation. All rights reserved.
/* --------------------------------------------------------------------------------------------
- ExtensionContext,
+ LanguageClientOptions,
* ------------------------------------------------------------------------------------------ */
- ExtensionContext,
+ LanguageClientOptions,
import * as path from 'path'
- * Copyright (c) Microsoft Corporation. All rights reserved.
+import * as path from 'path'
/* --------------------------------------------------------------------------------------------
- ExtensionContext,
+ LanguageClientOptions,
import {
- ExtensionContext,
+ LanguageClientOptions,
workspace as Workspace,
+ debug: {
+ LanguageClientOptions,
ExtensionContext,
- window as Window,
+/* --------------------------------------------------------------------------------------------
workspace as Workspace,
-import * as path from 'path'
+ options: debugOptions,
+/* --------------------------------------------------------------------------------------------
let serverOptions = {
+ }
+/* --------------------------------------------------------------------------------------------
run: { module, transport: TransportKind.ipc },
+/* --------------------------------------------------------------------------------------------
debug: { module, transport: TransportKind.ipc, options: debugOptions },
+/* --------------------------------------------------------------------------------------------
}
+/* --------------------------------------------------------------------------------------------
let clientOptions: LanguageClientOptions = {
- documentSelector: LANGUAGES.map((language) => ({
scheme: 'file',
language,
pattern: `${folder.uri.fsPath}/**/*`,
})),
+ diagnosticCollectionName: CLIENT_ID,
+ TransportKind,
window as Window,
/* --------------------------------------------------------------------------------------------
+ language,
/* --------------------------------------------------------------------------------------------
+ window as Window,
+} from 'vscode-languageclient'
/* --------------------------------------------------------------------------------------------
+/* --------------------------------------------------------------------------------------------
outputChannel: outputChannel,
/* --------------------------------------------------------------------------------------------
+ workspace as Workspace,
* Copyright (c) Microsoft Corporation. All rights reserved.
- workspace as Workspace,
import * as path from 'path'
+/* --------------------------------------------------------------------------------------------
/* --------------------------------------------------------------------------------------------
+ window as Window,
* Licensed under the MIT License. See License.txt in the project root for license information.
+/* --------------------------------------------------------------------------------------------
'lsp-multi-server-example',
+/* --------------------------------------------------------------------------------------------
'LSP Multi Server Example',
+/* --------------------------------------------------------------------------------------------
serverOptions,
+/* --------------------------------------------------------------------------------------------
clientOptions
+/* --------------------------------------------------------------------------------------------
)
/* --------------------------------------------------------------------------------------------
- * ------------------------------------------------------------------------------------------ */
+ defaultClient.start()
/* --------------------------------------------------------------------------------------------
+ ExtensionContext,
+/* --------------------------------------------------------------------------------------------
import * as path from 'path'
+ ExtensionContext,
+
+import { registerConfigErrorHandler } from './lib/registerConfigErrorHandler'
/* --------------------------------------------------------------------------------------------
+ clients.set(folder.uri.toString(), client)
+ }
+
import {
+/* --------------------------------------------------------------------------------------------
+import {
* Copyright (c) Microsoft Corporation. All rights reserved.
/* --------------------------------------------------------------------------------------------
+ if (!folder) {
+ return
+import * as path from 'path'
/* --------------------------------------------------------------------------------------------
+
+ let uri = document.uri
+ ExtensionContext,
+ // Files outside a folder can't be handled. This might depend on the language.
+ // Single file languages like JSON might handle files outside the workspace folders.
+ if (!folder) {
+import {
workspace as Workspace,
+import * as path from 'path'
/* --------------------------------------------------------------------------------------------
+ // If we have nested workspace folders we only start a server on the outer most workspace folder.
+ folder = getOuterMostWorkspaceFolder(folder)
+
+ if (!languages.has(folder.uri.toString())) {
+ languages.set(
+ folder.uri.toString(),
+ dedupe([...DEFAULT_LANGUAGES, ...Object.keys(getUserLanguages())])
+ window as Window,
window as Window,
}
+
+ bootWorkspaceClient(folder)
}
Workspace.onDidOpenTextDocument(didOpenTextDocument)
@@ -209,10 +273,6 @@ }
export function deactivate(): Thenable<void> {
OutputChannel,
- ExtensionContext,
- if (defaultClient) {
- promises.push(defaultClient.stop())
- * Licensed under the MIT License. See License.txt in the project root for license information.
ExtensionContext,
for (let client of clients.values()) {
promises.push(client.stop())
diff --git a/src/lib/languages.ts b/src/lib/languages.ts
index 8e1b859d9d8ed6f99e6bdc74ff43d75551faed42..b9238edde46be72d6b7a5db044b063e57666efff 100644
--- a/src/lib/languages.ts
+++ b/src/lib/languages.ts
@@ -1,4 +1,4 @@
-export const LANGUAGES = [
+export const DEFAULT_LANGUAGES = [
// html
'aspnetcorerazor',
'blade',
diff --git a/src/lsp/providers/completionProvider.ts b/src/lsp/providers/completionProvider.ts
index f1e9130abb7d978a454c163c3d289daa4184f067..4dc374518e5e6b8e9830031c19a26afb1cbb5cb6 100644
--- a/src/lsp/providers/completionProvider.ts
+++ b/src/lsp/providers/completionProvider.ts
@@ -191,16 +191,15 @@ ): CompletionList {
let doc = state.editor.documents.get(params.textDocument.uri)
if (
- isHtmlContext(doc, params.position) ||
+ isHtmlContext(state, doc, params.position) ||
-import { State } from '../util/state'
let replacementRange = {
+ CompletionParams,
) {
return provideClassAttributeCompletions(state, params)
}
-import { State } from '../util/state'
CompletionItemKind,
- CompletionItem,
+ Range,
return provideAtApplyCompletions(state, params)
}
@@ -213,9 +212,8 @@ { position, textDocument }: CompletionParams
): CompletionList {
let doc = state.editor.documents.get(textDocument.uri)
-import { State } from '../util/state'
CompletionItemKind,
- CompletionList,
+ MarkupKind,
return null
}
@@ -323,9 +321,8 @@ { position, textDocument }: CompletionParams
): CompletionList {
let doc = state.editor.documents.get(textDocument.uri)
-import { State } from '../util/state'
CompletionItemKind,
- CompletionList,
+ MarkupKind,
return null
}
@@ -416,9 +413,8 @@ { position, textDocument }: CompletionParams
): CompletionList {
let doc = state.editor.documents.get(textDocument.uri)
-import { State } from '../util/state'
CompletionItemKind,
- CompletionList,
+ MarkupKind,
return null
}
@@ -466,9 +462,8 @@ { position, textDocument }: CompletionParams
): CompletionList {
let doc = state.editor.documents.get(textDocument.uri)
-import { State } from '../util/state'
CompletionItemKind,
- CompletionList,
+ MarkupKind,
return null
}
@@ -516,9 +511,8 @@ { position, textDocument }: CompletionParams
): CompletionList {
let doc = state.editor.documents.get(textDocument.uri)
-import { State } from '../util/state'
CompletionItemKind,
- CompletionList,
+ MarkupKind,
return null
}
@@ -613,10 +607,10 @@ if (settings.emmetCompletions !== true) return null
let doc = state.editor.documents.get(textDocument.uri)
- const syntax = isHtmlContext(doc, position)
+ const syntax = isHtmlContext(state, doc, position)
? 'html'
-): CompletionList {
CompletionItemKind,
+} from 'vscode-languageserver'
? 'jsx'
: null
diff --git a/src/lsp/providers/hoverProvider.ts b/src/lsp/providers/hoverProvider.ts
index ce213758a18f24ae45a5f72ea00346e33b91d888..7e27d9ac9833ec166a6332607b38562ec0b03f80 100644
--- a/src/lsp/providers/hoverProvider.ts
+++ b/src/lsp/providers/hoverProvider.ts
@@ -27,8 +27,8 @@ { textDocument, position }: TextDocumentPositionParams
): Hover {
let doc = state.editor.documents.get(textDocument.uri)
+const dlv = require('dlv')
import { Hover, TextDocumentPositionParams } from 'vscode-languageserver'
-} from '../util/getClassNameAtPosition'
const line = doc.getText({
start: { line: position.line, character: 0 },
@@ -82,8 +82,12 @@ { textDocument, position }: TextDocumentPositionParams
): Hover {
let doc = state.editor.documents.get(textDocument.uri)
+ if (
+ !isHtmlContext(state, doc, position) &&
+const dlv = require('dlv')
getClassNameParts,
-import { isHtmlContext } from '../util/html'
+ )
+ return null
let hovered = getClassNameAtPosition(doc, position)
if (!hovered) return null
@@ -113,8 +117,8 @@ { textDocument, position }: TextDocumentPositionParams
): Hover {
let doc = state.editor.documents.get(textDocument.uri)
+const dlv = require('dlv')
import { Hover, TextDocumentPositionParams } from 'vscode-languageserver'
-} from '../util/getClassNameAtPosition'
const classNames = findClassNamesInRange(doc, {
start: { line: Math.max(position.line - 10, 0), character: 0 },
diff --git a/src/lsp/server.ts b/src/lsp/server.ts
index 3315853a892e72680b786a48e45987b70dc13f58..b28b1bad9d226222f5d9e24472c9d8d698df6187 100644
--- a/src/lsp/server.ts
+++ b/src/lsp/server.ts
@@ -32,8 +32,11 @@ let connection = createConnection(ProposedFeatures.all)
let documents = new TextDocuments()
let workspaceFolder: string | null
+const defaultSettings: Settings = {
+ emmetCompletions: false,
+ CompletionList,
* Licensed under the MIT License. See License.txt in the project root for license information.
- * Copyright (c) Microsoft Corporation. All rights reserved.
+}
let globalSettings: Settings = defaultSettings
let documentSettings: Map<string, Settings> = new Map()
@@ -54,6 +57,11 @@ connection,
documents,
documentSettings,
globalSettings,
+ userLanguages:
+ params.initializationOptions &&
+ params.initializationOptions.userLanguages
+ ? params.initializationOptions.userLanguages
+ : {},
capabilities: {
configuration:
capabilities.workspace && !!capabilities.workspace.configuration,
diff --git a/src/lsp/util/css.ts b/src/lsp/util/css.ts
index fb4f90a86a88412678b90e801df0d47764dbe4b1..84b788889c876707b4201ba3d2093b8bb472dd2f 100644
--- a/src/lsp/util/css.ts
+++ b/src/lsp/util/css.ts
@@ -1,5 +1,6 @@
import { TextDocument, Position } from 'vscode-languageserver'
import { isInsideTag, isVueDoc, isSvelteDoc } from './html'
+import { State } from './state'
export const CSS_LANGUAGES = [
'css',
@@ -10,16 +11,23 @@ 'scss',
'stylus',
]
-import { TextDocument, Position } from 'vscode-languageserver'
import { isInsideTag, isVueDoc, isSvelteDoc } from './html'
+ 'postcss',
-import { TextDocument, Position } from 'vscode-languageserver'
+ const userCssLanguages = Object.keys(
+ state.editor.userLanguages
+
+ return [...CSS_LANGUAGES, ...userCssLanguages].indexOf(doc.languageId) !== -1
}
-import { TextDocument, Position } from 'vscode-languageserver'
+export function isCssContext(
+ state: State,
+ doc: TextDocument,
+
'css',
-import { TextDocument, Position } from 'vscode-languageserver'
+
'less',
+ if (isCssDoc(state, doc)) {
return true
}
diff --git a/src/lsp/util/html.ts b/src/lsp/util/html.ts
index d0f5743546bb04975746961bc9419d7fbf35e130..8808141906f9545b6ad1c62f838acf6f52f0f88a 100644
--- a/src/lsp/util/html.ts
+++ b/src/lsp/util/html.ts
@@ -1,4 +1,5 @@
import { TextDocument, Position } from 'vscode-languageserver'
+import { State } from './state'
export const HTML_LANGUAGES = [
'aspnetcorerazor',
@@ -27,9 +28,14 @@ 'slim',
'twig',
]
+export function isHtmlDoc(state: State, doc: TextDocument): boolean {
+ const userHtmlLanguages = Object.keys(
+ state.editor.userLanguages
+ ).filter((lang) => HTML_LANGUAGES.includes(state.editor.userLanguages[lang]))
- 'erb',
- return HTML_LANGUAGES.indexOf(doc.languageId) !== -1
+ return (
+ [...HTML_LANGUAGES, ...userHtmlLanguages].indexOf(doc.languageId) !== -1
+ )
}
export function isVueDoc(doc: TextDocument): boolean {
@@ -40,14 +46,18 @@ export function isSvelteDoc(doc: TextDocument): boolean {
return doc.languageId === 'svelte'
}
+export function isHtmlContext(
+ state: State,
+ doc: TextDocument,
+ 'edge',
export const HTML_LANGUAGES = [
- 'django-html',
+): boolean {
let str = doc.getText({
start: { line: 0, character: 0 },
end: position,
})
- if (isHtmlDoc(doc) && !isInsideTag(str, ['script', 'style'])) {
+ if (isHtmlDoc(state, doc) && !isInsideTag(str, ['script', 'style'])) {
return true
}
diff --git a/src/lsp/util/js.ts b/src/lsp/util/js.ts
index 48107f079ef9569635bf1f87a246175c41bbad14..8a62a5ff69c8ff4869e8541c6d0eac40a9b1744e 100644
--- a/src/lsp/util/js.ts
+++ b/src/lsp/util/js.ts
@@ -1,5 +1,6 @@
import { TextDocument, Position } from 'vscode-languageserver'
import { isHtmlDoc, isInsideTag, isVueDoc, isSvelteDoc } from './html'
+import { State } from './state'
export const JS_LANGUAGES = [
'javascript',
@@ -8,15 +9,24 @@ 'reason',
'typescriptreact',
]
-export function isJsDoc(doc: TextDocument): boolean {
+export function isJsDoc(state: State, doc: TextDocument): boolean {
- return JS_LANGUAGES.indexOf(doc.languageId) !== -1
+ const userJsLanguages = Object.keys(
-import { TextDocument, Position } from 'vscode-languageserver'
import { isHtmlDoc, isInsideTag, isVueDoc, isSvelteDoc } from './html'
+ 'typescriptreact',
+ ).filter((lang) => JS_LANGUAGES.includes(state.editor.userLanguages[lang]))
+ return [...JS_LANGUAGES, ...userJsLanguages].indexOf(doc.languageId) !== -1
import { TextDocument, Position } from 'vscode-languageserver'
+import { isHtmlDoc, isInsideTag, isVueDoc, isSvelteDoc } from './html'
+
import { TextDocument, Position } from 'vscode-languageserver'
+ state: State,
+ doc: TextDocument,
+
export const JS_LANGUAGES = [
+): boolean {
+ if (isJsDoc(state, doc)) {
return true
}
@@ -25,7 +35,7 @@ start: { line: 0, character: 0 },
end: position,
})
- if (isHtmlDoc(doc) && isInsideTag(str, ['script'])) {
+ if (isHtmlDoc(state, doc) && isInsideTag(str, ['script'])) {
return true
}
diff --git a/src/lsp/util/state.ts b/src/lsp/util/state.ts
index 401cedfeb2252fe7752dc2768aa7f880f44c21fa..daaa0501c05f20e0e88dc85c4357533d26e4a74d 100644
--- a/src/lsp/util/state.ts
+++ b/src/lsp/util/state.ts
@@ -18,6 +18,7 @@ connection: Connection
documents: TextDocuments
documentSettings: Map<string, Settings>
globalSettings: Settings
+ userLanguages: Record<string, string>
capabilities: {
configuration: boolean
}
@@ -25,6 +26,7 @@ }
export type Settings = {
emmetCompletions: boolean
+ includeLanguages: Record<string, string>
}
export type State = null | {