Skip to content

Commit a54c8c5

Browse files
committed
wip
1 parent be5df62 commit a54c8c5

File tree

1 file changed

+72
-1
lines changed

1 file changed

+72
-1
lines changed

packages/tailwindcss-language-service/src/features/source-inline.ts

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,24 @@ import type { CodeLens } from 'vscode-languageserver'
88
import braces from 'braces'
99
import { findAll, indexToPosition } from '../util/find'
1010
import { absoluteRange } from '../util/absoluteRange'
11+
import { segment } from '../util/segment'
1112

1213
const PATTERN = /@source(?:\s+not)?\s*inline\((?<glob>'[^']+'|"[^"]+")/dg
1314

1415
export async function provideCodeLens(state: State, doc: TextDocument): Promise<CodeLens[]> {
1516
let text = doc.getText()
1617

18+
let countFormatter = new Intl.NumberFormat('en', {
19+
maximumFractionDigits: 2,
20+
})
21+
22+
let byteFormatter = new Intl.NumberFormat('en', {
23+
notation: 'compact',
24+
style: 'unit',
25+
unit: 'byte',
26+
unitDisplay: 'narrow',
27+
})
28+
1729
let lenses: CodeLens[] = []
1830

1931
for (let match of findAll(PATTERN, text)) {
@@ -28,14 +40,73 @@ export async function provideCodeLens(state: State, doc: TextDocument): Promise<
2840
end: indexToPosition(text, match.indices.groups.glob[1]),
2941
})
3042

43+
let size = 0
44+
for (let className of expanded) {
45+
size += approximateByteSize(className)
46+
}
47+
3148
lenses.push({
3249
range: slice,
3350
command: {
34-
title: `Generates ${expanded.size} classes`,
51+
title: `Generates ${countFormatter.format(expanded.size)} classes`,
3552
command: '',
3653
},
3754
})
55+
56+
if (size >= 1_000_000) {
57+
lenses.push({
58+
range: slice,
59+
command: {
60+
title: `At least ${byteFormatter.format(size)} of CSS`,
61+
command: '',
62+
},
63+
})
64+
65+
lenses.push({
66+
range: slice,
67+
command: {
68+
title: `This may slow down your bundler/browser`,
69+
command: '',
70+
},
71+
})
72+
}
3873
}
3974

4075
return lenses
4176
}
77+
78+
/**
79+
* Calculates the approximate size of a generated class
80+
*
81+
* This is meant to be a lower bound, as the actual size of a class can vary
82+
* depending on the actual CSS properties and values, configured theme, etc…
83+
*/
84+
function approximateByteSize(className: string) {
85+
let size = 0
86+
87+
// We estimate the size using the following structure which gives a reasonable
88+
// lower bound on the size of the generated CSS:
89+
//
90+
// .class-name {
91+
// &:variant-1 {
92+
// &:variant-2 {
93+
// /* properties */
94+
// }
95+
// }
96+
// }
97+
98+
// Class name
99+
size += 1 + className.length + 3
100+
size += 2
101+
102+
// Variants + nesting
103+
for (let [depth, variantName] of segment(className, ':').entries()) {
104+
size += (depth + 1) * 2 + 2 + variantName.length + 3
105+
size += (depth + 1) * 2 + 2
106+
}
107+
108+
// Properties comment
109+
size += 16
110+
111+
return size
112+
}

0 commit comments

Comments
 (0)