Skip to content

Commit 75d56a0

Browse files
committed
Show estimated number of classes generated above to @source inline(…)
1 parent 93027cf commit 75d56a0

File tree

4 files changed

+80
-1
lines changed

4 files changed

+80
-1
lines changed

packages/tailwindcss-language-server/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"@tailwindcss/line-clamp": "0.4.2",
4343
"@tailwindcss/oxide": "^4.0.0-alpha.19",
4444
"@tailwindcss/typography": "0.5.7",
45+
"@types/braces": "3.0.1",
4546
"@types/color-name": "^1.1.3",
4647
"@types/culori": "^2.1.0",
4748
"@types/debounce": "1.2.0",
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { expect } from 'vitest'
2+
import { css, defineTest } from '../../src/testing'
3+
import { createClient } from '../utils/client'
4+
5+
defineTest({
6+
name: 'Code lenses are displayed for @source inline(…)',
7+
fs: {
8+
'app.css': css`
9+
@import 'tailwindcss';
10+
`,
11+
},
12+
prepare: async ({ root }) => ({
13+
client: await createClient({ root }),
14+
}),
15+
handle: async ({ client }) => {
16+
let document = await client.open({
17+
lang: 'css',
18+
text: css`
19+
@import 'tailwindcss';
20+
@source inline("{,{hover,focus}:}{flex,underline,bg-red-{50,{100..900.100},950}}");
21+
`,
22+
})
23+
24+
let lenses = await document.codeLenses()
25+
26+
expect(lenses).toEqual([
27+
{
28+
range: {
29+
start: { line: 1, character: 15 },
30+
end: { line: 1, character: 81 },
31+
},
32+
command: {
33+
title: 'Generates 15 classes',
34+
command: '',
35+
},
36+
},
37+
])
38+
},
39+
})

packages/tailwindcss-language-service/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"vscode-languageserver-textdocument": "1.0.11"
4141
},
4242
"devDependencies": {
43+
"@types/braces": "3.0.1",
4344
"@types/css.escape": "^1.5.2",
4445
"@types/line-column": "^1.0.2",
4546
"@types/node": "^18.19.33",
Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,51 @@
1-
import type { TextDocument } from 'vscode-languageserver-textdocument'
1+
import type { Range, TextDocument } from 'vscode-languageserver-textdocument'
22
import type { State } from './util/state'
33
import type { CodeLens } from 'vscode-languageserver'
4+
import braces from 'braces'
5+
import { findAll, indexToPosition } from './util/find'
6+
import { absoluteRange } from './util/absoluteRange'
47

58
export async function getCodeLens(state: State, doc: TextDocument): Promise<CodeLens[]> {
69
if (!state.enabled) return []
710

811
let groups: CodeLens[][] = await Promise.all([
912
//
13+
sourceInlineCodeLens(state, doc),
1014
])
1115

1216
return groups.flat()
1317
}
18+
19+
const SOURCE_INLINE_PATTERN = /@source(?:\s+not)?\s*inline\((?<glob>'[^']+'|"[^"]+")/dg
20+
async function sourceInlineCodeLens(state: State, doc: TextDocument): Promise<CodeLens[]> {
21+
let text = doc.getText()
22+
23+
let countFormatter = new Intl.NumberFormat('en', {
24+
maximumFractionDigits: 2,
25+
})
26+
27+
let lenses: CodeLens[] = []
28+
29+
for (let match of findAll(SOURCE_INLINE_PATTERN, text)) {
30+
let glob = match.groups.glob.slice(1, -1)
31+
32+
// Perform brace expansion
33+
let expanded = new Set<string>(braces.expand(glob))
34+
if (expanded.size < 2) continue
35+
36+
let slice: Range = absoluteRange({
37+
start: indexToPosition(text, match.indices.groups.glob[0]),
38+
end: indexToPosition(text, match.indices.groups.glob[1]),
39+
})
40+
41+
lenses.push({
42+
range: slice,
43+
command: {
44+
title: `Generates ${countFormatter.format(expanded.size)} classes`,
45+
command: '',
46+
},
47+
})
48+
}
49+
50+
return lenses
51+
}

0 commit comments

Comments
 (0)