Skip to content

Commit 2e1e4be

Browse files
committed
feat: colors everywhere!
1 parent d022517 commit 2e1e4be

File tree

2 files changed

+130
-1
lines changed

2 files changed

+130
-1
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@
747747
]
748748
},
749749
"scripts": {
750-
"start": "vscode-framework start",
750+
"start": "vscode-framework start --skip-launching",
751751
"build": "vscode-framework build",
752752
"lint": "eslint src/**"
753753
},

src/features/colorsEverywhere.ts

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import * as vscode from 'vscode'
2+
3+
// Maximum file size in bytes to process (1MB)
4+
const MAX_FILE_SIZE = 1024 * 1024
5+
6+
// Regex patterns for matching colors
7+
const COLOR_PATTERNS = {
8+
hex: /#([\dA-Fa-f]{3}){1,2}\b/g,
9+
rgb: /rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)/g,
10+
rgba: /rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0|1|0?\.\d+)\s*\)/g
11+
}
12+
13+
function parseHexColor(hex: string): vscode.Color | undefined {
14+
hex = hex.slice(1) // Remove #
15+
let r = 0; let g = 0; let b = 0
16+
17+
if (hex.length === 3) {
18+
r = Number.parseInt(hex[0]! + hex[0]!, 16) / 255
19+
g = Number.parseInt(hex[1]! + hex[1]!, 16) / 255
20+
b = Number.parseInt(hex[2]! + hex[2]!, 16) / 255
21+
} else if (hex.length === 6) {
22+
r = Number.parseInt(hex.slice(0, 2), 16) / 255
23+
g = Number.parseInt(hex.slice(2, 4), 16) / 255
24+
b = Number.parseInt(hex.slice(4, 6), 16) / 255
25+
} else {
26+
return undefined
27+
}
28+
29+
return new vscode.Color(r, g, b, 1)
30+
}
31+
32+
function parseRgbColor(match: string): vscode.Color | undefined {
33+
const values = match.match(/\d+/g)
34+
if (!values || values.length < 3) return undefined
35+
36+
const rgbValues = values.slice(0, 3).map(v => {
37+
const parsed = Number.parseInt(v, 10)
38+
return Number.isNaN(parsed) ? undefined : parsed / 255
39+
})
40+
if (rgbValues.some(v => v === undefined || v < 0 || v > 1)) return undefined
41+
42+
const alpha = values.length === 4 ? Number.parseFloat(values[3]!) : 1
43+
return new vscode.Color(rgbValues[0]!, rgbValues[1]!, rgbValues[2]!, alpha)
44+
}
45+
46+
export default (): vscode.Disposable => vscode.languages.registerColorProvider(
47+
[
48+
{ language: 'typescript' },
49+
{ language: 'javascript' },
50+
{ language: 'typescriptreact' },
51+
{ language: 'javascriptreact' },
52+
],
53+
{
54+
async provideDocumentColors(
55+
document: vscode.TextDocument,
56+
token: vscode.CancellationToken
57+
): Promise<vscode.ColorInformation[]> {
58+
// Skip large files
59+
const textEncoder = new TextEncoder()
60+
const fileSize = textEncoder.encode(document.getText()).length
61+
if (fileSize > MAX_FILE_SIZE) {
62+
return []
63+
}
64+
65+
const text = document.getText()
66+
const colors: vscode.ColorInformation[] = []
67+
68+
// Match hex colors
69+
let match = COLOR_PATTERNS.hex.exec(text)
70+
while (match !== null) {
71+
const color = parseHexColor(match[0])
72+
if (color) {
73+
const range = new vscode.Range(
74+
document.positionAt(match.index),
75+
document.positionAt(match.index + match[0].length)
76+
)
77+
colors.push(new vscode.ColorInformation(range, color))
78+
}
79+
80+
match = COLOR_PATTERNS.hex.exec(text)
81+
}
82+
83+
// Match rgb/rgba colors
84+
const rgbPatterns = [COLOR_PATTERNS.rgb, COLOR_PATTERNS.rgba]
85+
for (const pattern of rgbPatterns) {
86+
let rgbMatch = pattern.exec(text)
87+
while (rgbMatch !== null) {
88+
const color = parseRgbColor(rgbMatch[0])
89+
if (color) {
90+
const range = new vscode.Range(
91+
document.positionAt(rgbMatch.index),
92+
document.positionAt(rgbMatch.index + rgbMatch[0].length)
93+
)
94+
colors.push(new vscode.ColorInformation(range, color))
95+
}
96+
97+
rgbMatch = pattern.exec(text)
98+
}
99+
}
100+
101+
return colors
102+
},
103+
104+
provideColorPresentations(
105+
color: vscode.Color,
106+
context: { document: vscode.TextDocument, range: vscode.Range },
107+
token: vscode.CancellationToken
108+
): vscode.ProviderResult<vscode.ColorPresentation[]> {
109+
const red = Math.round(color.red * 255)
110+
const green = Math.round(color.green * 255)
111+
const blue = Math.round(color.blue * 255)
112+
113+
const hex = `#${red.toString(16).padStart(2, '0')}${green.toString(16).padStart(2, '0')}${blue.toString(16).padStart(2, '0')}`
114+
115+
const presentations = [
116+
new vscode.ColorPresentation(hex),
117+
new vscode.ColorPresentation(`rgb(${red}, ${green}, ${blue})`)
118+
]
119+
120+
if (color.alpha !== 1) {
121+
presentations.push(
122+
new vscode.ColorPresentation(`rgba(${red}, ${green}, ${blue}, ${color.alpha.toFixed(2)})`)
123+
)
124+
}
125+
126+
return presentations
127+
}
128+
}
129+
)

0 commit comments

Comments
 (0)