Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify hovers #881

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/tailwindcss-language-server/src/server.ts
Expand Up @@ -251,6 +251,7 @@ async function getConfiguration(uri?: string) {
classAttributes: ['class', 'className', 'ngClass'],
codeActions: true,
hovers: true,
simplifyHovers: true,
suggestions: true,
validate: true,
colorDecorators: true,
Expand Down
Expand Up @@ -114,7 +114,7 @@ withFixture('basic', (c) => {
detail: 'text-transform: uppercase;',
documentation: {
kind: 'markdown',
value: '```css\n.uppercase {\n text-transform: uppercase;\n}\n```',
value: '```css\n& {\n text-transform: uppercase;\n}\n```',
},
})
})
Expand Down
Expand Up @@ -13,7 +13,7 @@ withFixture('multi-config-content', (c) => {
contents: {
language: 'css',
value:
'.bg-foo {\n --tw-bg-opacity: 1;\n background-color: rgb(255 0 0 / var(--tw-bg-opacity));\n}',
'& {\n --tw-bg-opacity: 1;\n background-color: rgb(255 0 0 / var(--tw-bg-opacity));\n}',
},
range: { start: { line: 0, character: 12 }, end: { line: 0, character: 18 } },
})
Expand All @@ -30,7 +30,7 @@ withFixture('multi-config-content', (c) => {
contents: {
language: 'css',
value:
'.bg-foo {\n --tw-bg-opacity: 1;\n background-color: rgb(0 0 255 / var(--tw-bg-opacity));\n}',
'& {\n --tw-bg-opacity: 1;\n background-color: rgb(0 0 255 / var(--tw-bg-opacity));\n}',
},
range: { start: { line: 0, character: 12 }, end: { line: 0, character: 18 } },
})
Expand Down
Expand Up @@ -13,7 +13,7 @@ withFixture('multi-config', (c) => {
contents: {
language: 'css',
value:
'.bg-foo {\n --tw-bg-opacity: 1;\n background-color: rgb(255 0 0 / var(--tw-bg-opacity));\n}',
'& {\n --tw-bg-opacity: 1;\n background-color: rgb(255 0 0 / var(--tw-bg-opacity));\n}',
},
range: { start: { line: 0, character: 12 }, end: { line: 0, character: 18 } },
})
Expand All @@ -30,7 +30,7 @@ withFixture('multi-config', (c) => {
contents: {
language: 'css',
value:
'.bg-foo {\n --tw-bg-opacity: 1;\n background-color: rgb(0 0 255 / var(--tw-bg-opacity));\n}',
'& {\n --tw-bg-opacity: 1;\n background-color: rgb(0 0 255 / var(--tw-bg-opacity));\n}',
},
range: { start: { line: 0, character: 12 }, end: { line: 0, character: 18 } },
})
Expand Down
25 changes: 21 additions & 4 deletions packages/tailwindcss-language-server/tests/hover/hover.test.js
Expand Up @@ -36,7 +36,7 @@ withFixture('basic', (c) => {
text: '<div class="bg-red-500">',
position: { line: 0, character: 13 },
expected:
'.bg-red-500 {\n' +
'& {\n' +
' --tw-bg-opacity: 1;\n' +
' background-color: rgb(239 68 68 / var(--tw-bg-opacity));\n' +
'}',
Expand All @@ -49,7 +49,7 @@ withFixture('basic', (c) => {
testHover('arbitrary value', {
text: '<div class="p-[3px]">',
position: { line: 0, character: 13 },
expected: '.p-\\[3px\\] {\n' + ' padding: 3px;\n' + '}',
expected: '& {\n' + ' padding: 3px;\n' + '}',
expectedRange: {
start: { line: 0, character: 12 },
end: { line: 0, character: 19 },
Expand All @@ -59,7 +59,7 @@ withFixture('basic', (c) => {
testHover('arbitrary value with theme function', {
text: '<div class="p-[theme(spacing.4)]">',
position: { line: 0, character: 13 },
expected: '.p-\\[theme\\(spacing\\.4\\)\\] {\n' + ' padding: 1rem/* 16px */;\n' + '}',
expected: '& {\n' + ' padding: 1rem/* 16px */;\n' + '}',
expectedRange: {
start: { line: 0, character: 12 },
end: { line: 0, character: 32 },
Expand All @@ -69,10 +69,27 @@ withFixture('basic', (c) => {
testHover('arbitrary property', {
text: '<div class="[text-wrap:balance]">',
position: { line: 0, character: 13 },
expected: '.\\[text-wrap\\:balance\\] {\n' + ' text-wrap: balance;\n' + '}',
expected: '& {\n' + ' text-wrap: balance;\n' + '}',
expectedRange: {
start: { line: 0, character: 12 },
end: { line: 0, character: 31 },
},
})

testHover('disable simplified hovers', {
text: '<div class="[[data-important]_&]:bg-purple-300">',
position: { line: 0, character: 13 },
settings: {
tailwindCSS: { simplifyHovers: false },
},
expected:
'[data-important] .\\[\\[data-important\\]_\\&\\]\\:bg-purple-300 {\n' +
' --tw-bg-opacity: 1;\n' +
' background-color: rgb(216 180 254 / var(--tw-bg-opacity));\n' +
'}',
expectedRange: {
start: { line: 0, character: 12 },
end: { line: 0, character: 46 },
},
})
})
Expand Up @@ -1416,7 +1416,7 @@ export async function resolveCompletionItem(
if (!item.documentation) {
item.documentation = {
kind: 'markdown' as typeof MarkupKind.Markdown,
value: ['```css', await jit.stringifyRoot(state, root), '```'].join('\n'),
value: ['```css', await jit.stringifyRoot(state, root, className), '```'].join('\n'),
}
}
return item
Expand Down
4 changes: 2 additions & 2 deletions packages/tailwindcss-language-service/src/hoverProvider.ts
@@ -1,5 +1,5 @@
import { State } from './util/state'
import type { Hover, Position } from 'vscode-languageserver'
import type { Hover, Position } from 'vscode-languageserver'
import { stringifyCss, stringifyConfigValue } from './util/stringify'
import dlv from 'dlv'
import { isCssContext } from './util/css'
Expand Down Expand Up @@ -71,7 +71,7 @@ async function provideClassNameHover(
return {
contents: {
language: 'css',
value: await jit.stringifyRoot(state, root, document.uri),
value: await jit.stringifyRoot(state, root, className.className, document.uri),
},
range: className.range,
}
Expand Down
16 changes: 15 additions & 1 deletion packages/tailwindcss-language-service/src/util/jit.ts
@@ -1,5 +1,6 @@
import { State } from './state'
import type { Container, Document, Root, Rule, Node, AtRule } from 'postcss'
import escapeClassName from 'css.escape'
import { addPixelEquivalentsToCss, addPixelEquivalentsToValue } from './pixelEquivalents'

export function bigSign(bigIntValue) {
Expand Down Expand Up @@ -33,14 +34,27 @@ export function generateRules(
}
}

export async function stringifyRoot(state: State, root: Root, uri?: string): Promise<string> {
export async function stringifyRoot(
state: State,
root: Root,
className: string,
uri?: string
): Promise<string> {
let settings = await state.editor.getConfiguration(uri)
let clone = root.clone()

clone.walkAtRules('defaults', (node) => {
node.remove()
})

if (settings.tailwindCSS.simplifyHovers) {
clone.walkRules((rule) => {
rule.selectors = rule.selectors.map((selector) => {
return selector.replace(`.${escapeClassName(className)}`, '&')
})
})
}

let css = clone.toString()

if (settings.tailwindCSS.showPixelEquivalents) {
Expand Down
1 change: 1 addition & 0 deletions packages/tailwindcss-language-service/src/util/state.ts
Expand Up @@ -46,6 +46,7 @@ export type TailwindCssSettings = {
classAttributes: string[]
suggestions: boolean
hovers: boolean
simplifyHovers: boolean
codeActions: boolean
validate: boolean
showPixelEquivalents: boolean
Expand Down
7 changes: 4 additions & 3 deletions packages/tailwindcss-language-service/src/util/stringify.ts
Expand Up @@ -49,7 +49,7 @@ export function stringifyCss(className: string, obj: any, settings: Settings): s
.join('\n')
return `${acc}${i === 0 ? '' : '\n'}${propStr}`
}, '')
css += `${indentStr}${augmentClassName(className, obj)} {\n${decls}\n${indentStr}}`
css += `${indentStr}${augmentClassName(className, obj, settings)} {\n${decls}\n${indentStr}}`

for (let i = context.length - 1; i >= 0; i--) {
css += `${indent.repeat(i)}\n}`
Expand All @@ -62,8 +62,9 @@ export function stringifyCss(className: string, obj: any, settings: Settings): s
return css
}

function augmentClassName(className: string, obj: any): string {
function augmentClassName(className: string, obj: any, settings: Settings): string {
const classSelector = settings.tailwindCSS.simplifyHovers ? '&' : `.${escapeClassName(className)}`
const pseudo = obj.__pseudo.join('')
const scope = obj.__scope ? `${obj.__scope} ` : ''
return `${scope}.${escapeClassName(className)}${pseudo}`
return `${scope}${classSelector}${pseudo}`
}
1 change: 1 addition & 0 deletions packages/vscode-tailwindcss/CHANGELOG.md
Expand Up @@ -3,6 +3,7 @@
## 0.11.x (Pre-Release)

- Enable Sort Selection on a remote host (#878)
- Add `simplifyHovers` option that replaces the class name with the ampersand (#881)

## 0.10.2

Expand Down
4 changes: 4 additions & 0 deletions packages/vscode-tailwindcss/README.md
Expand Up @@ -108,6 +108,10 @@ Root font size in pixels. Used to convert `rem` CSS values to their `px` equival

Enable hovers. **Default: `true`**

### `tailwindCSS.simplifyHovers`

Simplify hovers to use the CSS nesting selector (`&`) in place of the class name. **Default: `true`**

### `tailwindCSS.suggestions`

Enable autocomplete suggestions. **Default: `true`**
Expand Down
6 changes: 6 additions & 0 deletions packages/vscode-tailwindcss/package.json
Expand Up @@ -195,6 +195,12 @@
"markdownDescription": "Enable hovers.",
"scope": "language-overridable"
},
"tailwindCSS.simplifyHovers": {
"type": "boolean",
"default": true,
"markdownDescription": "Simplify hovers to use the CSS nesting selector (`&`) in place of the class name.",
"scope": "language-overridable"
},
"tailwindCSS.codeActions": {
"type": "boolean",
"default": true,
Expand Down