diff --git a/packages/vscode/src/autocomplete.ts b/packages/vscode/src/autocomplete.ts index 0513174666..f844413b43 100644 --- a/packages/vscode/src/autocomplete.ts +++ b/packages/vscode/src/autocomplete.ts @@ -3,7 +3,7 @@ import { createAutocomplete } from '@unocss/autocomplete' import type { CompletionItemProvider, ExtensionContext } from 'vscode' import { CompletionItem, CompletionItemKind, CompletionList, MarkdownString, Range, languages } from 'vscode' import type { UnoGenerator, UnocssPluginContext } from '@unocss/core' -import { getPrettiedMarkdown, isCssId, isSubdir } from './utils' +import { body2ColorValue, getPrettiedCSS, getPrettiedMarkdown, isCssId, isSubdir } from './utils' import { log } from './log' import type { ContextLoader } from './contextLoader' @@ -90,11 +90,21 @@ export async function registerAutoComplete( if (!result.suggestions.length) return + const theme = ctx?.uno.config.theme return new CompletionList(result.suggestions.map(([value, label]) => { + const colorValue = theme ? body2ColorValue(value, theme) : null + const itemKind = colorValue?.color ? CompletionItemKind.Color : CompletionItemKind.EnumMember + const resolved = result.resolveReplacement(value) - const item = new UnoCompletionItem(label, CompletionItemKind.EnumMember, ctx!.uno) + const item = new UnoCompletionItem(label, itemKind, ctx!.uno) item.insertText = resolved.replacement item.range = new Range(doc.positionAt(resolved.start), doc.positionAt(resolved.end)) + + if (colorValue?.color) { + item.documentation = colorValue?.color + item.sortText = /-\d$/.test(label) ? '1' : '2' // reorder color completions + } + return item }), true) } @@ -105,10 +115,11 @@ export async function registerAutoComplete( }, async resolveCompletionItem(item) { - return { - ...item, - documentation: await getMarkdown(item.uno, item.label as string), - } + if (item.kind === CompletionItemKind.Color) + item.detail = await (await getPrettiedCSS(item.uno, item.label as string)).prettified + else + item.documentation = await getMarkdown(item.uno, item.label as string) + return item }, } diff --git a/packages/vscode/src/utils.ts b/packages/vscode/src/utils.ts index c20c8d9a4f..ed4994d9c6 100644 --- a/packages/vscode/src/utils.ts +++ b/packages/vscode/src/utils.ts @@ -40,12 +40,26 @@ export async function getPrettiedMarkdown(uno: UnoGenerator, util: string) { return `\`\`\`css\n${(await getPrettiedCSS(uno, util)).prettified}\n\`\`\`` } +export function body2ColorValue(body: string, theme: Theme) { + const themeColorNames = Object.keys(theme.colors ?? {}) + const colorNames = themeColorNames.concat(themeColorNames.map(colorName => colorName.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase())) + + for (const colorName of colorNames) { + const nameIndex = body.indexOf(colorName) + if (nameIndex > -1) { + const parsedResult = parseColor(body.substring(nameIndex), theme) + if (parsedResult?.cssColor) + return parsedResult + } + } + + return null +} + const matchedAttributifyRE = /(?<=^\[.+~?=").*(?="\]$)/ const _colorsMapCache = new Map() export function getColorsMap(uno: UnoGenerator, result: GenerateResult) { const theme = uno.config.theme as Theme - const themeColorNames = Object.keys(theme.colors ?? {}) - const colorNames = themeColorNames.concat(themeColorNames.map(colorName => colorName.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase())) const colorsMap = new Map() for (const i of result.matched) { @@ -56,20 +70,13 @@ export function getColorsMap(uno: UnoGenerator, result: GenerateResult) { } const matchedAttr = i.match(matchedAttributifyRE) - const body = matchedAttr ? matchedAttr[0].split(':').at(-1) ?? '' : i // remove prefix e.g. `dark:` `hover:` - - for (const colorName of colorNames) { - const nameIndex = body.indexOf(colorName) - if (nameIndex > -1) { - const parsedResult = parseColor(body.substring(nameIndex), theme) - if (parsedResult?.cssColor) { - const color = colorToString(parsedResult.cssColor, parsedResult.alpha) - colorsMap.set(_i, color) - _colorsMapCache.set(_i, color) - } + const body = matchedAttr?.[0] ?? i // remove prefix e.g. `dark:` `hover:` - break - } + const colorValue = body2ColorValue(body, theme) + if (colorValue) { + const colorString = colorToString(colorValue.cssColor!, colorValue.alpha) + colorsMap.set(_i, colorString) + _colorsMapCache.set(_i, colorString) } }