Skip to content

Commit

Permalink
feat(vscode): color preview in suggestions (#1202)
Browse files Browse the repository at this point in the history
  • Loading branch information
zam157 committed Jul 1, 2022
1 parent 77438ab commit 884599d
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 21 deletions.
23 changes: 17 additions & 6 deletions packages/vscode/src/autocomplete.ts
Expand Up @@ -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'

Expand Down Expand Up @@ -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)
}
Expand All @@ -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
},
}

Expand Down
37 changes: 22 additions & 15 deletions packages/vscode/src/utils.ts
Expand Up @@ -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<string, string>()
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<string, string>()

for (const i of result.matched) {
Expand All @@ -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)
}
}

Expand Down

0 comments on commit 884599d

Please sign in to comment.