Skip to content

Commit 5227b39

Browse files
committed
fix: "better" completion labels
1 parent 90f5418 commit 5227b39

File tree

3 files changed

+50
-20
lines changed

3 files changed

+50
-20
lines changed

src/colors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const KNOWN_COLORS = new Set(['transparent', 'currentColor'])
1+
export const KNOWN_COLORS = new Set(['transparent', 'currentColor'])
22

33
const NAMED_COLORS = new Map([
44
['aliceblue', '#f0f8ff'],

src/language-service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ export class TwindLanguageService implements TemplateLanguageService {
184184
JSON.stringify(
185185
{
186186
[completion.theme.section]: {
187-
[completion.theme.key]: completion.theme.value,
187+
[completion.theme.key || '…']: completion.theme.value || '…',
188188
},
189189
},
190190
null,

src/twind.ts

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as path from 'path'
22
import Module from 'module'
3-
import { fileURLToPath, pathToFileURL } from 'url'
3+
import { fileURLToPath } from 'url'
44

55
import type { Logger } from 'typescript-template-language-service-decorator'
66
import type * as TS from 'typescript/lib/tsserverlibrary'
@@ -22,7 +22,7 @@ import type {
2222
import { theme, create, silent } from 'twind'
2323
import { VirtualSheet, virtualSheet } from 'twind/sheets'
2424
import { getConfig, loadFile } from './load'
25-
import { getColor } from './colors'
25+
import { getColor, KNOWN_COLORS } from './colors'
2626

2727
import type { ConfigurationManager } from './configuration'
2828
import { watch } from './watch'
@@ -102,19 +102,17 @@ const detailsFromThemeValue = <Section extends keyof Theme>(
102102
.filter(Boolean)
103103
.join('/')
104104
}
105-
}
106105

107-
if (typeof value == 'string') return value
108-
if (typeof value == 'number') return '' + value
106+
case 'fontFamily': {
107+
return Array.isArray(value) ? value.filter(Boolean).join(', ') : (value as string)
108+
}
109+
}
109110

110-
// https://github.com/tailwindlabs/tailwindcss/blob/master/src/util/transformThemeValue.js
111-
// only testing for sections that uses an array for values
112111
if (
113-
Array.isArray(value) &&
114-
!['fontSize', 'outline'].includes(section) &&
115-
value.every((x) => x == null || typeof x == 'string' || typeof x == 'number')
112+
typeof value == 'string' &&
113+
((/color/i.test(section) && !KNOWN_COLORS.has(value)) || /\s/.test(value))
116114
) {
117-
return value.filter(Boolean).join(', ')
115+
return value
118116
}
119117

120118
return undefined
@@ -566,7 +564,7 @@ export class Twind {
566564
detailsFromThemeValue(theme.section, theme.value),
567565
),
568566
)) ||
569-
interpolation ||
567+
translateInterpolation(interpolation) ||
570568
detailFromCSS(sheet, tw, value, interpolation))
571569
)
572570
},
@@ -646,7 +644,7 @@ export class Twind {
646644
createCompletionToken(className, {
647645
kind: screens.has(className) ? 'screen' : undefined,
648646
raw: directive,
649-
detail: key == '[' ? 'arbitrary value' : undefined,
647+
label: className.endsWith('[') && key === '[' ? `${className}…]` : undefined,
650648
theme:
651649
key == '['
652650
? { section: sectionKey as keyof Theme, key: '', value: '' }
@@ -671,6 +669,7 @@ export class Twind {
671669
prefix,
672670
createCompletionToken(prefix, {
673671
raw: directive,
672+
label: `${prefix}${suffix}`,
674673
interpolation: value as CompletionToken['interpolation'],
675674
}),
676675
)
@@ -702,7 +701,11 @@ function generateCSS(
702701
sheet.reset()
703702

704703
if (interpolation) {
705-
value += getSampleInterpolation(interpolation)
704+
value = value.replace(//g, getSampleInterpolation(interpolation))
705+
}
706+
707+
if (value.endsWith('-[')) {
708+
value += '…]'
706709
}
707710

708711
if (value.endsWith(':')) {
@@ -730,14 +733,21 @@ function generateCSS(
730733
.trim()
731734
}
732735

736+
// TODO do not match @keyframes
737+
const CSS_DECLARATION_RE = /[{;]\s*([A-Z\d-]+)\s*:\s*([^;}]+)/gi
738+
733739
function detailFromCSS(
734740
sheet: VirtualSheet,
735741
tw: TW,
736742
value: string,
737743
interpolation?: CompletionToken['interpolation'],
738744
): string {
739745
if (interpolation) {
740-
value += getSampleInterpolation(interpolation)
746+
value = value.replace(//g, getSampleInterpolation(interpolation))
747+
}
748+
749+
if (value.endsWith('-[')) {
750+
value += '…]'
741751
}
742752

743753
let style: CSSRules = {}
@@ -757,7 +767,7 @@ function detailFromCSS(
757767

758768
// - if at-rule use at rule
759769
// - if variant: use &:hover, &>*
760-
if (key && /^@|&/.test(key)) {
770+
if (value.endsWith(':') && key && /^@|&/.test(key)) {
761771
// TODO beautify children: siblings
762772
// TODO order of suggestions
763773
// TODO grouping prefix is ommited
@@ -768,9 +778,14 @@ function detailFromCSS(
768778
const css = generateCSS(sheet, tw, value)
769779

770780
let result = ''
771-
for (const [, property, value] of css.matchAll(/[{;]\s*([A-Z\d-]+)\s*:\s*([^;}]+)/gi)) {
781+
782+
// Reset as we break early
783+
CSS_DECLARATION_RE.lastIndex = 0
784+
for (let match: RegExpExecArray | null; (match = CSS_DECLARATION_RE.exec(css)); ) {
785+
const [, property, value] = match
786+
772787
if (result.length < 30) {
773-
result += (result && '; ') + `${property}: ${value}`
788+
result += (result && '; ') + `${property}: ${convertRem(value)}`
774789
} else {
775790
result += '; …'
776791
break
@@ -779,3 +794,18 @@ function detailFromCSS(
779794

780795
return result
781796
}
797+
798+
function translateInterpolation(
799+
interpolation?: CompletionToken['interpolation'],
800+
): string | undefined {
801+
switch (interpolation) {
802+
case `string`: // NonEmptyString
803+
return 'any string'
804+
case `number`: // NonNegativeNumber
805+
return 'a number greater or equal zero'
806+
case `nonzero`: // PositiveNumber
807+
return 'a number greater zero'
808+
}
809+
810+
return interpolation
811+
}

0 commit comments

Comments
 (0)