diff --git a/packages/tailwindcss-language-server/src/server.ts b/packages/tailwindcss-language-server/src/server.ts index a038aeab6f556f6c34d088e0f2109c57a8b26300..721a37b4cf41b06187ffa8e580559f0e1d6c366f 100644 --- a/packages/tailwindcss-language-server/src/server.ts +++ b/packages/tailwindcss-language-server/src/server.ts @@ -74,7 +74,7 @@ import { getModuleDependencies } from './util/getModuleDependencies' import assert from 'assert' // import postcssLoadConfig from 'postcss-load-config' import * as parcel from './watcher/index.js' -import { bigSign } from 'tailwindcss-language-service/src/util/jit' +import { generateRules } from 'tailwindcss-language-service/src/util/jit' import { getColor } from 'tailwindcss-language-service/src/util/color' import * as culori from 'culori' import namedColors from 'color-name' @@ -195,7 +195,6 @@ onDocumentColor(params: DocumentColorParams): Promise onColorPresentation(params: ColorPresentationParams): Promise onCodeAction(params: CodeActionParams): Promise onDocumentLinks(params: DocumentLinkParams): DocumentLink[] - sortClassLists(classLists: string[]): string[] } type ProjectConfig = { @@ -534,7 +533,6 @@ }) state.enabled = false refreshDiagnostics() updateCapabilities() - connection.sendNotification('@/tailwindCSS/projectReset') } async function tryInit() { @@ -543,7 +541,6 @@ return } try { await init() - connection.sendNotification('@/tailwindCSS/projectInitialized') } catch (error) { resetState() showError(connection, error) @@ -1273,70 +1270,9 @@ // round numbers .replace(/\d+\.\d+(%?)/g, (value, suffix) => `${Math.round(parseFloat(value))}${suffix}`), ].map((value) => ({ label: `${prefix}-[${value}]` })) }, - sortClassLists(classLists: string[]): string[] { - if (!state.jit) { - return classLists - } - - return classLists.map((classList) => { - let result = '' - let parts = classList.split(/(\s+)/) - let classes = parts.filter((_, i) => i % 2 === 0) - let whitespace = parts.filter((_, i) => i % 2 !== 0) - - if (classes[classes.length - 1] === '') { - classes.pop() - } - - let classNamesWithOrder = state.jitContext.getClassOrder - ? state.jitContext.getClassOrder(classes) - : getClassOrderPolyfill(state, classes) - - classes = classNamesWithOrder - .sort(([, a], [, z]) => { - if (a === z) return 0 - if (a === null) return -1 - if (z === null) return 1 - return bigSign(a - z) - }) - .map(([className]) => className) - - for (let i = 0; i < classes.length; i++) { - result += `${classes[i]}${whitespace[i] ?? ''}` - } - - return result - }) - }, } } -function prefixCandidate(state: State, selector: string) { - let prefix = state.config.prefix - return typeof prefix === 'function' ? prefix(selector) : prefix + selector -} - -function getClassOrderPolyfill(state: State, classes: string[]): Array<[string, bigint]> { - let parasiteUtilities = new Set([prefixCandidate(state, 'group'), prefixCandidate(state, 'peer')]) - - let classNamesWithOrder = [] - - for (let className of classes) { - let order = - state.modules.jit.generateRules - .module(new Set([className]), state.jitContext) - .sort(([a], [z]) => bigSign(z - a))[0]?.[0] ?? null - - if (order === null && parasiteUtilities.has(className)) { - order = state.jitContext.layerOrder.components - } - - classNamesWithOrder.push([className, order]) - } - - return classNamesWithOrder -} - function isObject(value: unknown): boolean { return Object.prototype.toString.call(value) === '[object Object]' } @@ -2214,39 +2150,6 @@ this.connection.onDocumentColor(this.onDocumentColor.bind(this)) this.connection.onColorPresentation(this.onColorPresentation.bind(this)) this.connection.onCodeAction(this.onCodeAction.bind(this)) this.connection.onDocumentLinks(this.onDocumentLinks.bind(this)) - this.connection.onRequest(this.onRequest.bind(this)) - } - - private onRequest( - method: '@/tailwindCSS/sortSelection', - params: { uri: string; classLists: string[] } - ): { error: string } | { classLists: string[] } - private onRequest( - method: '@/tailwindCSS/getProject', - params: { uri: string } - ): { version: string } | null - private onRequest(method: string, params: any): any { - if (method === '@/tailwindCSS/sortSelection') { - let project = this.getProject({ uri: params.uri }) - if (!project) { - return { error: 'no-project' } - } - try { - return { classLists: project.sortClassLists(params.classLists) } - } catch { - return { error: 'unknown' } - } - } - - if (method === '@/tailwindCSS/getProject') { - let project = this.getProject({ uri: params.uri }) - if (!project || !project.enabled() || !project.state?.enabled) { - return null - } - return { - version: project.state.version, - } - } } private updateCapabilities() { @@ -2367,7 +2270,6 @@ this.connection.listen() } dispose(): void { - connection.sendNotification('@/tailwindCSS/projectsDestroyed') for (let [, project] of this.projects) { project.dispose() } diff --git a/packages/tailwindcss-language-server/tests/commands/commands.test.js b/packages/tailwindcss-language-server/tests/commands/commands.test.js deleted file mode 100644 index a9683254de27dc7787d4600b363d185f3e4e4226..0000000000000000000000000000000000000000 --- a/packages/tailwindcss-language-server/tests/commands/commands.test.js +++ /dev/null @@ -1,14 +0,0 @@ -import { test, expect } from 'vitest' -import { withFixture } from '../common' - -withFixture('basic', (c) => { - test.concurrent('sortSelection', async () => { - let textDocument = await c.openDocument({ text: '
' }) - let res = await c.sendRequest('@/tailwindCSS/sortSelection', { - uri: textDocument.uri, - classLists: ['sm:p-0 p-0'], - }) - - expect(res).toEqual({ classLists: ['p-0 sm:p-0'] }) - }) -}) diff --git a/packages/vscode-tailwindcss/README.md b/packages/vscode-tailwindcss/README.md index 714b3808ad9fe93e98bd5d05110398e5399f4403..af40434f59b9c64bcbda3012e60cc46bfc962bd6 100644 --- a/packages/vscode-tailwindcss/README.md +++ b/packages/vscode-tailwindcss/README.md @@ -54,16 +54,6 @@ "strings": "on" } ``` -## Extension Commands - -### `Tailwind CSS: Show Output` - -Reveal the language server log panel. This command is only available when there is an active language server instance. - -### `Tailwind CSS: Sort Selection` (pre-release) - -When a list of CSS classes is selected this command can be used to sort them in [the same order that Tailwind orders them in your CSS](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted). This command is only available when the current document belongs to an active Tailwind project and the `tailwindcss` version is `3.0.0` or greater. - ## Extension Settings ### `tailwindCSS.includeLanguages` diff --git a/packages/vscode-tailwindcss/package.json b/packages/vscode-tailwindcss/package.json index cb00b41e32032a0ae6b5fb4d69b2e14deefa11c3..87fef321bc34858f66057ce22d96c740ab7ba937 100755 --- a/packages/vscode-tailwindcss/package.json +++ b/packages/vscode-tailwindcss/package.json @@ -60,11 +60,6 @@ { "command": "tailwindCSS.showOutput", "title": "Tailwind CSS: Show Output", "enablement": "tailwindCSS.hasOutputChannel" - }, - { - "command": "tailwindCSS.sortSelection", - "title": "Tailwind CSS: Sort Selection", - "enablement": "editorHasSelection && resourceScheme == file && tailwindCSS.activeTextEditorSupportsClassSorting" } ], "grammars": [ diff --git a/packages/vscode-tailwindcss/src/extension.ts b/packages/vscode-tailwindcss/src/extension.ts index 9139983dfc2fd21e0ec9b93b9f4f48e826b6be79..ac8951b8b58e4e439b17b523d1987768cf487bfb 100755 --- a/packages/vscode-tailwindcss/src/extension.ts +++ b/packages/vscode-tailwindcss/src/extension.ts @@ -27,7 +27,6 @@ ProviderResult, SnippetString, TextEdit, TextEditorSelectionChangeKind, - Selection, } from 'vscode' import { LanguageClient, @@ -39,7 +38,6 @@ RevealOutputChannelOn, Disposable, } from 'vscode-languageclient/node' import { languages as defaultLanguages } from 'tailwindcss-language-service/src/util/languages' -import * as semver from 'tailwindcss-language-service/src/util/semver' import isObject from 'tailwindcss-language-service/src/util/isObject' import { dedupe, equal } from 'tailwindcss-language-service/src/util/array' import namedColors from 'color-name' @@ -123,71 +121,6 @@ async function fileContainsAtConfig(uri: Uri) { let contents = (await Workspace.fs.readFile(uri)).toString() return /@config\s*['"]/.test(contents) -} - -function selectionsAreEqual( - aSelections: readonly Selection[], - bSelections: readonly Selection[] -): boolean { - if (aSelections.length !== bSelections.length) { - return false - } - for (let i = 0; i < aSelections.length; i++) { - if (!aSelections[i].isEqual(bSelections[i])) { - return false - } - } - return true -} - -async function getActiveTextEditorProject(): Promise<{ version: string } | null> { - if (clients.size === 0) { - return null - } - let editor = Window.activeTextEditor - if (!editor) { - return null - } - let uri = editor.document.uri - let folder = Workspace.getWorkspaceFolder(uri) - if (!folder) { - return null - } - let client = clients.get(folder.uri.toString()) - if (!client) { - return null - } - if (isExcluded(uri.fsPath, folder)) { - return null - } - try { - let project = await client.sendRequest<{ version: string } | null>('@/tailwindCSS/getProject', { - uri: uri.toString(), - }) - return project - } catch { - return null - } -} - -async function activeTextEditorSupportsClassSorting(): Promise { - let project = await getActiveTextEditorProject() - if (!project) { - return false - } - return semver.gte(project.version, '3.0.0') -} - -async function updateActiveTextEditorContext(): Promise { - commands.executeCommand( - 'setContext', - 'tailwindCSS.activeTextEditorSupportsClassSorting', - await activeTextEditorSupportsClassSorting() - ) -} - -function resetActiveTextEditorContext(): void { - commands.executeCommand('setContext', 'tailwindCSS.activeTextEditorSupportsClassSorting', false) } export async function activate(context: ExtensionContext) { @@ -206,72 +139,6 @@ commands.registerCommand('tailwindCSS.showOutput', () => { if (outputChannel) { outputChannel.show() } - }) - ) - - async function sortSelection(): Promise { - let { document, selections } = Window.activeTextEditor - - if (selections.length === 0) { - return - } - - let initialSelections = selections - let folder = Workspace.getWorkspaceFolder(document.uri) - - if (clients.size === 0 || !folder || isExcluded(document.uri.fsPath, folder)) { - throw Error(`No active Tailwind project found for file ${document.uri.fsPath}`) - } - - let client = clients.get(folder.uri.toString()) - if (!client) { - throw Error(`No active Tailwind project found for file ${document.uri.fsPath}`) - } - - let result = await client.sendRequest<{ error: string } | { classLists: string[] }>( - '@/tailwindCSS/sortSelection', - { - uri: document.uri.toString(), - classLists: selections.map((selection) => document.getText(selection)), - } - ) - - if ( - Window.activeTextEditor.document !== document || - !selectionsAreEqual(initialSelections, Window.activeTextEditor.selections) - ) { - return - } - - if ('error' in result) { - throw Error( - { - 'no-project': `No active Tailwind project found for file ${document.uri.fsPath}`, - }[result.error] ?? 'An unknown error occurred.' - ) - } - - let sortedClassLists = result.classLists - Window.activeTextEditor.edit((builder) => { - for (let i = 0; i < selections.length; i++) { - builder.replace(selections[i], sortedClassLists[i]) - } - }) - } - - context.subscriptions.push( - commands.registerCommand('tailwindCSS.sortSelection', async () => { - try { - await sortSelection() - } catch (error) { - Window.showWarningMessage(`Couldn’t sort Tailwind classes: ${error.message}`) - } - }) - ) - - context.subscriptions.push( - Window.onDidChangeActiveTextEditor(async () => { - await updateActiveTextEditorContext() }) ) @@ -752,16 +619,6 @@ } }) client.onNotification('@/tailwindCSS/clearColors', () => clearColors()) - - client.onNotification('@/tailwindCSS/projectInitialized', async () => { - await updateActiveTextEditorContext() - }) - client.onNotification('@/tailwindCSS/projectReset', async () => { - await updateActiveTextEditorContext() - }) - client.onNotification('@/tailwindCSS/projectsDestroyed', () => { - resetActiveTextEditorContext() - }) client.onRequest('@/tailwindCSS/getDocumentSymbols', async ({ uri }) => { return commands.executeCommand(