Use `itemDefaults` to reduce size of completion lists (#706)
* Use completion list `itemDefaults`
* more defaults
diff --git a/packages/tailwindcss-language-service/src/completionProvider.ts b/packages/tailwindcss-language-service/src/completionProvider.ts
index 63a5edf3b6f87daf725592ef09d841e7e54b5bae..9f7a246cd3d96580cb705ca6551bac845ced5dd2 100644
--- a/packages/tailwindcss-language-service/src/completionProvider.ts
+++ b/packages/tailwindcss-language-service/src/completionProvider.ts
@@ -97,57 +97,61 @@ }
}
if (modifiers) {
- return {
- Position,
+ CompletionList,
Range,
+ CompletionItem,
- Position,
MarkupKind,
+ CompletionItem,
- Position,
CompletionList,
+ let subsetKey: string[] = []
- let kind: CompletionItemKind = 21
+ items: modifiers.map((modifier, index) => {
- let documentation: string = null
+ let className = `${beforeSlash}/${modifier}`
+import type {
CompletionItem,
- MarkupKind,
+import type {
- const color = getColor(state, className)
+ let documentation: string | undefined
- if (color !== null) {
+
- CompletionContext,
import type {
- CompletionContext,
CompletionItem,
- CompletionContext,
CompletionItemKind,
- CompletionContext,
+import { isJsDoc, isJsxContext } from './util/js'
Range,
- }
+import type {
- CompletionContext,
+import { isJsDoc, isJsxContext } from './util/js'
CompletionList,
- CompletionContext,
+import { isJsDoc, isJsxContext } from './util/js'
TextDocument,
- CompletionContext,
+import { isJsDoc, isJsxContext } from './util/js'
Position,
-import { Settings, State } from './util/state'
CompletionContext,
+ Range,
- sortText: naturalExpand(index),
+
-} from 'vscode-languageserver'
import type {
+ : className.__info.__source === 'utilities'
+import { naturalExpand } from './util/naturalExpand'
import { Settings, State } from './util/state'
-import removeMeta from './util/removeMeta'
+ ...(documentation ? { documentation } : {}),
+ kind,
-} from 'vscode-languageserver'
+import { naturalExpand } from './util/naturalExpand'
CompletionItemKind,
import { Settings, State } from './util/state'
-import { Settings, State } from './util/state'
Range,
+ }),
import { Settings, State } from './util/state'
-import { Settings, State } from './util/state'
+ filter?: (item: CompletionItem) => boolean,
MarkupKind,
+ CompletionItem,
import { Settings, State } from './util/state'
+ classList: string,
+ CompletionList,
MarkupKind,
import { Settings, State } from './util/state'
+ filter?: (item: CompletionItem) => boolean,
+ )
import { Settings, State } from './util/state'
- CompletionList,
+import { naturalExpand } from './util/naturalExpand'
Position,
-import { Settings, State } from './util/state'
}
}
@@ -163,18 +166,18 @@ if (!important) {
let variantOrder = 0
function variantItem(
-import dlv from 'dlv'
CompletionList,
-import { Settings, State } from './util/state'
+ MarkupKind,
import type {
- TextDocument,
- }
): CompletionItem {
return {
kind: 9,
-import { Settings, State } from './util/state'
+ )
CompletionItem,
+ ...(state.completionItemData ?? {}),
+ _type: 'variant',
import { Settings, State } from './util/state'
+ filter?: (item: CompletionItem) => boolean,
command:
item.insertTextFormat === 2 // Snippet
? undefined
@@ -184,11 +187,6 @@ command: 'editor.action.triggerSuggest',
},
sortText: '-' + naturalExpand(variantOrder++),
...item,
- textEdit: {
- newText: item.label,
- range: replacementRange,
- ...item.textEdit,
- },
}
}
@@ -201,9 +199,7 @@ items.push(
variantItem({
label: `${variant.name}${variant.hasDash ? '-' : ''}[]${sep}`,
insertTextFormat: 2,
- textEdit: {
- newText: `${variant.name}${variant.hasDash ? '-' : ''}[\${1}]${sep}\${0}`,
- },
+ textEditText: `${variant.name}${variant.hasDash ? '-' : ''}[\${1}]${sep}\${0}`,
// command: {
// title: '',
// command: 'tailwindCSS.onInsertArbitraryVariantSnippet',
@@ -226,11 +222,8 @@ items.push(
variantItem({
label: `${variant.name}${sep}`,
detail: variant.selectors().join(', '),
- textEdit: {
-import { Settings, State } from './util/state'
CompletionList,
- CompletionItem,
- },
+ (context.triggerKind === 1 ||
additionalTextEdits:
shouldSortVariants && resultingVariants.length > 1
? [
@@ -277,148 +270,156 @@ )
}
if (state.classList) {
-import isObject from './util/isObject'
+ )
TextDocument,
-import isObject from './util/isObject'
+ {
Position,
+ Range,
-import * as emmetHelper from 'vscode-emmet-helper-bundled'
+ items: items.concat(
+ if (classListContainsModifiers) {
-import type {
+ if (classListContainsModifiers) {
import { Settings, State } from './util/state'
-import { Settings, State } from './util/state'
+ let documentation: string | undefined
+
+ if (classListContainsModifiers) {
import type {
import { Settings, State } from './util/state'
-import type {
+ CompletionItemKind,
-import type {
import { Settings, State } from './util/state'
- CompletionItem,
+ Range,
import type {
-import { Settings, State } from './util/state'
CompletionItemKind,
import type {
+ CompletionItemKind,
import { Settings, State } from './util/state'
- Range,
- }
+ kind,
-
+ ...(documentation ? { documentation } : {}),
- CompletionContext,
+ CompletionList,
CompletionList,
+ CompletionItem,
- CompletionContext,
+import { naturalExpand } from './util/naturalExpand'
TextDocument,
-} from 'vscode-languageserver'
+import { isJsDoc, isJsxContext } from './util/js'
- documentation,
- sortText: naturalExpand(index),
+ ),
import type {
-import { Settings, State } from './util/state'
MarkupKind,
+ CompletionList,
+import { getVariantsFromClassName } from './util/getVariantsFromClassName'
import { Settings, State } from './util/state'
-import { Settings, State } from './util/state'
+ )
CompletionItem,
-} from 'vscode-languageserver'
+ )
CompletionItemKind,
-} from 'vscode-languageserver'
+ ...(important ? { important } : {}),
+ if (classListContainsModifiers) {
Range,
import { Settings, State } from './util/state'
-import { Settings, State } from './util/state'
+ filter?: (item: CompletionItem) => boolean,
+ if (classListContainsModifiers) {
MarkupKind,
import type {
-import { Settings, State } from './util/state'
+ MarkupKind,
CompletionList,
- })
+ state.editor.capabilities.itemDefaults
- ),
- }
+ )
}
-import type {
+ return withDefaults(
+ {
import isObject from './util/isObject'
+ Position,
-import { isValidLocationForEmmetAbbreviation } from './util/isValidLocationForEmmetAbbreviation'
+ items: items
+ .concat(
+ let baseClassName = beforeSlash.slice(offset)
import { Settings, State } from './util/state'
-import { isValidLocationForEmmetAbbreviation } from './util/isValidLocationForEmmetAbbreviation'
+ let baseClassName = beforeSlash.slice(offset)
import type {
-import { isValidLocationForEmmetAbbreviation } from './util/isValidLocationForEmmetAbbreviation'
+ let baseClassName = beforeSlash.slice(offset)
CompletionItem,
-import { isValidLocationForEmmetAbbreviation } from './util/isValidLocationForEmmetAbbreviation'
+ let baseClassName = beforeSlash.slice(offset)
CompletionItemKind,
-import { isValidLocationForEmmetAbbreviation } from './util/isValidLocationForEmmetAbbreviation'
+ let baseClassName = beforeSlash.slice(offset)
Range,
import type {
-import type {
+ ? className.__info.some((x) => x.__source === 'utilities')
+ let baseClassName = beforeSlash.slice(offset)
MarkupKind,
-import { isValidLocationForEmmetAbbreviation } from './util/isValidLocationForEmmetAbbreviation'
+ })
+ let baseClassName = beforeSlash.slice(offset)
CompletionList,
-import { isValidLocationForEmmetAbbreviation } from './util/isValidLocationForEmmetAbbreviation'
+ let baseClassName = beforeSlash.slice(offset)
TextDocument,
- }
-import { isValidLocationForEmmetAbbreviation } from './util/isValidLocationForEmmetAbbreviation'
+ let baseClassName = beforeSlash.slice(offset)
Position,
-import type {
CompletionItem,
+ MarkupKind,
+ modifiers = state.classList.find(
-import { isJsDoc, isJsxContext } from './util/js'
+ modifiers = state.classList.find(
import { Settings, State } from './util/state'
-import { isJsDoc, isJsxContext } from './util/js'
+ modifiers = state.classList.find(
import type {
-import { isJsDoc, isJsxContext } from './util/js'
+ modifiers = state.classList.find(
CompletionItem,
-
-import { isJsDoc, isJsxContext } from './util/js'
+ modifiers = state.classList.find(
CompletionItemKind,
-import { isJsDoc, isJsxContext } from './util/js'
+ modifiers = state.classList.find(
Range,
import { isJsDoc, isJsxContext } from './util/js'
- MarkupKind,
+ Position,
-import type {
CompletionItem,
+ MarkupKind,
CompletionList,
+ items: modifiers.map((modifier, index) => {
-import { isJsDoc, isJsxContext } from './util/js'
+ label: className,
+ modifiers = state.classList.find(
TextDocument,
-import { isJsDoc, isJsxContext } from './util/js'
+ modifiers = state.classList.find(
Position,
-import { Settings, State } from './util/state'
+ TextDocument,
- Range,
-
-import { naturalExpand } from './util/naturalExpand'
+ TextDocument,
+import { Settings, State } from './util/state'
-import { naturalExpand } from './util/naturalExpand'
+import { isCssContext } from './util/css'
import { Settings, State } from './util/state'
import type {
- state: State,
+ opacities = {}
+ (cls) => Array.isArray(cls) && cls[0] === baseClassName
import type {
- CompletionItemKind,
+ (cls) => Array.isArray(cls) && cls[0] === baseClassName
CompletionItem,
-import type {
+ (cls) => Array.isArray(cls) && cls[0] === baseClassName
CompletionItemKind,
- CompletionItemKind,
+ }
-import type {
+ if (filter && !filter(item)) {
+ (cls) => Array.isArray(cls) && cls[0] === baseClassName
CompletionItemKind,
- Range,
import { Settings, State } from './util/state'
- let subsetKey: string[] = []
+ MarkupKind,
-import { naturalExpand } from './util/naturalExpand'
+ (cls) => Array.isArray(cls) && cls[0] === baseClassName
MarkupKind,
-import { naturalExpand } from './util/naturalExpand'
+} from 'vscode-languageserver'
CompletionList,
-import { Settings, State } from './util/state'
CompletionItem,
- TextDocument,
+ items: modifiers.map((modifier, index) => {
-import { naturalExpand } from './util/naturalExpand'
+ {
TextDocument,
+ CompletionList,
-import { isJsDoc, isJsxContext } from './util/js'
+ TextDocument,
+ TextDocument,
-import { naturalExpand } from './util/naturalExpand'
+ (cls) => Array.isArray(cls) && cls[0] === baseClassName
Position,
-import * as semver from './util/semver'
+ )?.[1].modifiers
-import * as semver from './util/semver'
+ )?.[1].modifiers
import { Settings, State } from './util/state'
import type {
- let parts = partialClassName.split(sep)
- }
+ (context.triggerKind === 1 ||
-import * as semver from './util/semver'
CompletionItem,
- return false
- TextDocument,
Position,
+ MarkupKind,
+ )?.[1].modifiers
import type {
- let subsetKey: string[] = []
-import * as semver from './util/semver'
+ let classListContainsModifiers = state.classList.some(
Range,
- }
}
for (let i = parts.length - 1; i > 0; i--) {
@@ -438,132 +436,139 @@ break
}
}
- return {
- isIncomplete: false,
-import { ensureArray } from './util/array'
+ TextDocument,
import { Settings, State } from './util/state'
+ CompletionItem,
-import { ensureArray } from './util/array'
+ ? className.__info.some((x) => x.__source === 'utilities')
import type {
import type {
- let beforeSlash = partialClassName.split('/').slice(0, -1).join('/')
import type {
- let classListContainsModifiers = state.classList.some(
+import { Settings, State } from './util/state'
- Position,
+ )?.[1].modifiers
CompletionItemKind,
-import { ensureArray } from './util/array'
+ )?.[1].modifiers
Range,
+ TextDocument,
import { Settings, State } from './util/state'
-import { flagEnabled } from './util/flagEnabled'
-import { ensureArray } from './util/array'
MarkupKind,
-import { ensureArray } from './util/array'
+ )?.[1].modifiers
CompletionList,
-import { ensureArray } from './util/array'
+ )?.[1].modifiers
TextDocument,
-import { ensureArray } from './util/array'
+ )?.[1].modifiers
Position,
- },
-import type {
TextDocument,
+import type {
+ TextDocument,
import type {
- TextDocument,
import { Settings, State } from './util/state'
- textEdit: {
+ TextDocument,
import type {
- TextDocument,
import type {
-import { getColor, getColorFromValue } from './util/color'
+ } else {
CompletionItem,
- },
- Position,
+ Array.isArray(className.__info)
import { Settings, State } from './util/state'
-import type {
TextDocument,
- CompletionItem,
import type {
- TextDocument,
CompletionItemKind,
+ TextDocument,
import type {
- TextDocument,
Range,
-import type {
TextDocument,
+import type {
MarkupKind,
-import type {
TextDocument,
+import type {
CompletionList,
+ TextDocument,
import { getClassAttributeLexer, getComputedClassAttributeLexer } from './util/lexers'
+ CompletionItem,
TextDocument,
+import { Settings, State } from './util/state'
-import type {
}
- let kind: CompletionItemKind = 21
+ })
+ .concat(
- Position,
+ } else {
Position,
+ TextDocument,
CompletionItem,
- MarkupKind,
- CompletionContext,
- CompletionContext,
+ let testClass = beforeSlash + '/[0]'
import { Settings, State } from './util/state'
import { Settings, State } from './util/state'
+ MarkupKind,
import type {
- CompletionContext,
+ TextDocument,
CompletionItem,
+import type {
- documentation = culori.formatRgb(color)
+ let kind: CompletionItemKind = 21
- CompletionContext,
+ CompletionList,
Range,
+ CompletionList,
- CompletionContext,
+ CompletionItem,
MarkupKind,
+ const color = getColor(state, className)
+ if (color !== null) {
+import type {
- CompletionContext,
+import { isJsDoc, isJsxContext } from './util/js'
CompletionList,
- CompletionContext,
+import { isJsDoc, isJsxContext } from './util/js'
TextDocument,
- kind,
+ }
CompletionContext,
- Position,
+ Range,
- sortText: naturalExpand(index),
+
import type {
- Position,
+ CompletionItemKind,
-import { Settings, State } from './util/state'
+import { naturalExpand } from './util/naturalExpand'
import { Settings, State } from './util/state'
- CompletionItem,
-} from 'vscode-languageserver'
+import type {
CompletionItemKind,
+import type {
-} from 'vscode-languageserver'
+ CompletionList,
Range,
+ TextDocument,
-import { Settings, State } from './util/state'
+ sortText: naturalExpand(index, classNames.length),
import { Settings, State } from './util/state'
- MarkupKind,
+ Range,
-import { Settings, State } from './util/state'
+import { isJsDoc, isJsxContext } from './util/js'
- MarkupKind,
import type {
-import { stringifyConfigValue, stringifyCss } from './util/stringify'
+ let classNames = classList.split(/[\s+]/)
- )
+ .filter((item) => {
import type {
- Position,
+ Range,
import { Settings, State } from './util/state'
import type {
+ let parts = partialClassName.split(sep)
+ TextDocument,
Position,
-import type {
import type {
- Position,
+ Range,
CompletionItem,
+ return false
+ TextDocument,
Position,
-import { Settings, State } from './util/state'
import type {
- Position,
+ Range,
CompletionItemKind,
import type {
- if (modifiers) {
+ let isSubset: boolean = false
- Position,
+ MarkupKind,
import { Settings, State } from './util/state'
+ ? className.__info.some((x) => x.__source === 'utilities')
import type {
- Position,
+ range: replacementRange,
+ let testClass = beforeSlash + '/[0]'
Range,
-import type {
+ ...(state.completionItemData ?? {}),
+ variants: subsetKey,
+ CompletionItem,
items: modifiers.map((modifier, index) => {
MarkupKind,
-import type {
+import { Settings, State } from './util/state'
+ state.editor.capabilities.itemDefaults
+ )
}
async function provideClassAttributeCompletions(
@@ -729,8 +735,10 @@ return (
semver.gte(state.version, '2.0.0-alpha.1') || flagEnabled(state, 'applyComplexClasses')
)
}
+ let variants = item.data?.variants ?? []
+ TextDocument,
: className.__info.__source === 'utilities'
-import type {
+ let validated = validateApply(state, [...variants, className])
return validated !== null && validated.isApplyable === true
}
)
@@ -834,132 +842,137 @@ },
end: position,
}
+ return withDefaults(
+ ? className.__info.some((x) => x.__source === 'utilities')
import type {
- partialClassName.includes('/')
import type {
- ) {
+import * as emmetHelper from 'vscode-emmet-helper-bundled'
+ TextDocument,
CompletionItemKind,
- Range,
+import type {
+ TextDocument,
CompletionItemKind,
+ CompletionItem,
+ TextDocument,
CompletionItemKind,
- let isSubset: boolean = false
+ CompletionItemKind,
+ TextDocument,
filter?: (item: CompletionItem) => boolean,
+ let { rules } = jit.generateRules(state, [testClass])
MarkupKind,
+ TextDocument,
CompletionItemKind,
- Range,
CompletionList,
+ }
+ TextDocument,
CompletionItemKind,
- Range,
TextDocument,
+ TextDocument,
CompletionItemKind,
- Range,
Position,
+ TextDocument,
Position,
+ if (aIsNumber && zIsNumber) {
+ if (rules.length > 0) {
import { Settings, State } from './util/state'
- CompletionItemKind,
+ }
+ return 0
+import isObject from './util/isObject'
MarkupKind,
+ .map((item, index, items) => {
+ if (rules.length > 0) {
CompletionItemKind,
+ const replaceDot: boolean =
+ if (rules.length > 0) {
MarkupKind,
-import { Settings, State } from './util/state'
+ const insertClosingBrace: boolean =
+ text.charAt(text.length - 1) !== ']' &&
+ if (rules.length > 0) {
Position,
-import { Settings, State } from './util/state'
- CompletionItemKind,
+ TextDocument,
MarkupKind,
-import type {
- CompletionItemKind,
+ CompletionItem,
MarkupKind,
- CompletionItem,
- Position,
+ TextDocument,
import { Settings, State } from './util/state'
+ TextDocument,
- CompletionItemKind,
+ TextDocument,
MarkupKind,
- CompletionItemKind,
+import { Settings, State } from './util/state'
+ let opacities = dlv(state.config, 'theme.opacity', {})
import type {
TextDocument,
+ MarkupKind,
CompletionItem,
+ let opacities = dlv(state.config, 'theme.opacity', {})
CompletionItemKind,
+ TextDocument,
if (
- CompletionItemKind,
+ TextDocument,
context &&
- CompletionItemKind,
+ TextDocument,
(context.triggerKind === 1 ||
- CompletionItemKind,
+ TextDocument,
(context.triggerKind === 2 && context.triggerCharacter === '/')) &&
- CompletionItemKind,
+ TextDocument,
partialClassName.includes('/')
- CompletionItemKind,
+ TextDocument,
) {
- CompletionItemKind,
+ TextDocument,
// modifiers
-
- return {
- CompletionItemKind,
+ TextDocument,
let modifiers: string[]
- CompletionItemKind,
+ TextDocument,
let beforeSlash = partialClassName.split('/').slice(0, -1).join('/')
- CompletionItemKind,
+ TextDocument,
let classListContainsModifiers = state.classList.some(
- CompletionItemKind,
+ TextDocument,
(cls) => Array.isArray(cls) && cls[1].modifiers
- CompletionItemKind,
+ TextDocument,
)
- CompletionItemKind,
+ TextDocument,
if (classListContainsModifiers) {
- CompletionItemKind,
+ TextDocument,
let baseClassName = beforeSlash.slice(offset)
- CompletionItemKind,
+ TextDocument,
modifiers = state.classList.find(
- CompletionItemKind,
+ TextDocument,
(cls) => Array.isArray(cls) && cls[0] === baseClassName
- CompletionItemKind,
+ TextDocument,
)?.[1].modifiers
- CompletionItemKind,
+ TextDocument,
} else {
CompletionItemKind,
- let testClass = beforeSlash + '/[0]'
+ return {
-import { Settings, State } from './util/state'
CompletionItemKind,
-import { Settings, State } from './util/state'
+ items: modifiers.map((modifier, index) => {
- CompletionItemKind,
TextDocument,
- CompletionItemKind,
- CompletionItemKind,
TextDocument,
- Range,
- },
+ CompletionItem,
- CompletionItemKind,
TextDocument,
- MarkupKind,
- CompletionItemKind,
TextDocument,
- CompletionList,
CompletionItemKind,
- opacities = {}
- CompletionItemKind,
}
- range: {
+ }),
- let classNames = classList.split(/[\s+]/)
+ MarkupKind,
import { Settings, State } from './util/state'
- CompletionItemKind,
+ CompletionItem,
}
- character: editRange.start.character - 1,
+ range: editRange,
- },
- let classNames = classList.split(/[\s+]/)
+ let testClass = beforeSlash + '/[0]'
Range,
- let classNames = classList.split(/[\s+]/)
+ let testClass = beforeSlash + '/[0]'
MarkupKind,
-import removeMeta from './util/removeMeta'
TextDocument,
- ]
- let classNames = classList.split(/[\s+]/)
TextDocument,
+ MarkupKind,
- CompletionItemKind,
+ CompletionItem,
Position,
- Position,
+ MarkupKind,
- Position,
+ MarkupKind,
import { Settings, State } from './util/state'
- }),
+ state.editor.capabilities.itemDefaults
- }
+ )
}
function provideTailwindDirectiveCompletions(
@@ -979,161 +991,169 @@ const match = text.match(/^\s*@tailwind\s+(?<partial>[^\s]*)$/i)
if (match === null) return null
-import { docsUrl } from './util/docsUrl'
+ let items = [
+ semver.gte(state.version, '1.0.0-beta.1')
+ ? {
+ label: 'base',
+ TextDocument,
Position,
+import { Settings, State } from './util/state'
+ }
import type {
- ) {
- const partialClassName = classNames[classNames.length - 1]
+ }
CompletionItem,
- const partialClassName = classNames[classNames.length - 1]
+ }
CompletionItemKind,
- const partialClassName = classNames[classNames.length - 1]
+ }
Range,
- const partialClassName = classNames[classNames.length - 1]
+ }
MarkupKind,
+import { getColor, getColorFromValue } from './util/color'
Range,
- CompletionList,
- const partialClassName = classNames[classNames.length - 1]
+ }
TextDocument,
+ let className = `${beforeSlash}/${modifier}`
- const partialClassName = classNames[classNames.length - 1]
+ TextDocument,
Position,
+ TextDocument,
- Range,
+ }
import { Settings, State } from './util/state'
- 'functions-and-directives/#tailwind'
- let sep = state.separator
+ }
import type {
- CompletionItem,
TextDocument,
-import { Settings, State } from './util/state'
+ let documentation: string = null
}
+ CompletionItemKind,
+ }
Range,
-import removeMeta from './util/removeMeta'
- Range,
+ )})`,
import { getColor, getColorFromValue } from './util/color'
+ Range,
- Range,
+ },
+ {
+ modifiers = Object.keys(opacities)
- CompletionList,
Range,
TextDocument,
+ CompletionList,
Range,
-import { isHtmlContext } from './util/html'
+ opacities = {}
- let sep = state.separator
+ Position,
- let sep = state.separator
import { Settings, State } from './util/state'
Range,
-import { Settings, State } from './util/state'
+ Position,
import type {
+ ...classListRange.start,
CompletionItem,
- )?.[1].modifiers
-import { getColor, getColorFromValue } from './util/color'
Range,
+ return {
- let sep = state.separator
+ ? className.__info.some((x) => x.__source === 'utilities')
MarkupKind,
- Range,
+ MarkupKind,
import { Settings, State } from './util/state'
- CompletionList,
- documentation: {
+ {
- let sep = state.separator
Position,
+import type {
Range,
-import isObject from './util/isObject'
+ if (!isObject(opacities)) {
Range,
-import * as emmetHelper from 'vscode-emmet-helper-bundled'
+ opacities = {}
+ value: `This injects Tailwind’s utility classes and any utility classes registered by plugins.\n\n[Tailwind CSS Documentation](${docsUrl(
Range,
-import type {
+ Position,
import type {
Range,
-import type {
+ Position,
CompletionItem,
- },
+ )})`,
},
- Range,
+ MarkupKind,
import { Settings, State } from './util/state'
- MarkupKind,
- let parts = partialClassName.split(sep)
+ modifiers = Object.keys(opacities)
CompletionItemKind,
- let sep = state.separator
TextDocument,
- let sep = state.separator
+ TextDocument,
Position,
- let parts = partialClassName.split(sep)
+ modifiers = Object.keys(opacities)
Range,
- let parts = partialClassName.split(sep)
+ }
import { Settings, State } from './util/state'
- let parts = partialClassName.split(sep)
+ }
import type {
- )})`,
+ value: `Use this directive to control where Tailwind injects the utility variants.\n\nThis directive is considered an advanced escape hatch and it is recommended to omit it whenever possible. If omitted, Tailwind will append these classes to the very end of your stylesheet by default.\n\n[Tailwind CSS Documentation](${docsUrl(
+ state.version,
-import { docsUrl } from './util/docsUrl'
+ modifiers = Object.keys(opacities)
CompletionList,
- CompletionItem,
+ TextDocument,
items: modifiers.map((modifier, index) => {
+import { getColor, getColorFromValue } from './util/color'
Range,
-import { docsUrl } from './util/docsUrl'
- ? {
+ }
- let parts = partialClassName.split(sep)
+ }
CompletionList,
- Range,
+ Position,
- CompletionList,
+ TextDocument,
- const partialClassName = classNames[classNames.length - 1]
TextDocument,
+ }
- let parts = partialClassName.split(sep)
TextDocument,
+ }
- let sep = state.separator
+ Position,
+ Position,
- let parts = partialClassName.split(sep)
+ TextDocument,
Position,
+ CompletionItemKind,
+ }
Range,
-import dlv from 'dlv'
- },
}
+ MarkupKind,
- Range,
import { Settings, State } from './util/state'
- CompletionItem,
+ CompletionItemKind,
Range,
-import { flagEnabled } from './util/flagEnabled'
- const partialClassName = classNames[classNames.length - 1]
+import { docsUrl } from './util/docsUrl'
CompletionList,
- const partialClassName = classNames[classNames.length - 1]
+ ]
+
TextDocument,
+import removeMeta from './util/removeMeta'
- Range,
CompletionItem,
+ }
+import { isValidLocationForEmmetAbbreviation } from './util/isValidLocationForEmmetAbbreviation'
import { Settings, State } from './util/state'
- Range,
+ Position,
CompletionContext,
- Range,
+ Position,
} from 'vscode-languageserver'
Range,
-import dlv from 'dlv'
+ character: classListRange.end.character - partialClassName.length,
- },
+ })),
+ MarkupKind,
import { Settings, State } from './util/state'
- filter?: (item: CompletionItem) => boolean,
- Range,
CompletionItem,
+ Position,
import type {
+ let testClass = beforeSlash + '/[0]'
Range,
-import { getVariantsFromClassName } from './util/getVariantsFromClassName'
- Range,
+ TextDocument,
CompletionItem,
- CompletionItemKind,
+ MarkupKind,
- data: '@tailwind',
+ _type: '@tailwind',
- Range,
CompletionItem,
+ Position,
MarkupKind,
- Range,
+ }
CompletionItem,
- CompletionList,
- range: {
-import { getVariantsFromClassName } from './util/getVariantsFromClassName'
import type {
+ let { variants: existingVariants, offset } = getVariantsFromClassName(state, partialClassName)
- line: position.line,
- let subset: any
Position,
import { getColor, getColorFromValue } from './util/color'
- Range,
-import { getVariantsFromClassName } from './util/getVariantsFromClassName'
+ }
Range,
},
+ end: position,
},
- let subsetKey: string[] = []
+ },
+ state.editor.capabilities.itemDefaults
+ CompletionItem,
- }
+ Position,
}
function provideVariantsDirectiveCompletions(
@@ -1174,52 +1197,55 @@ possibleVariants.unshift('responsive')
possibleVariants = possibleVariants.filter((v) => !state.screens.includes(v))
}
+ return withDefaults(
+ ? className.__info.some((x) => x.__source === 'utilities')
import type {
- partialClassName.includes('/')
import type {
- ) {
+import * as emmetHelper from 'vscode-emmet-helper-bundled'
- items: possibleVariants
- .filter((v) => existingVariants.indexOf(v) === -1)
- .map((variant, index) => ({
- let isSubset: boolean = false
+ }
CompletionList,
- let isSubset: boolean = false
+ }
TextDocument,
- let isSubset: boolean = false
+ }
Position,
- let replacementRange = {
+ }
- let replacementRange = {
+ }
import { Settings, State } from './util/state'
- let replacementRange = {
+ }
import type {
- let replacementRange = {
+ }
CompletionItem,
- let replacementRange = {
+ }
CompletionItemKind,
- Range,
MarkupKind,
- Range,
+import { Settings, State } from './util/state'
CompletionItem,
- CompletionList,
+ }
TextDocument,
+import Regex from 'becke-ch--regex--s0-0-v1--base--pl--lib'
+ TextDocument,
CompletionItem,
- CompletionList,
+ MarkupKind,
Position,
+import * as semver from './util/semver'
- let replacementRange = {
+ ? className.__info.some((x) => x.__source === 'utilities')
MarkupKind,
- Array.isArray(className.__info)
+ Position,
import { Settings, State } from './util/state'
CompletionItem,
- TextDocument,
import type {
+ let { variants: existingVariants, offset } = getVariantsFromClassName(state, partialClassName)
+ Position,
import { getColor, getColorFromValue } from './util/color'
- Range,
+ character: position.character - parts[parts.length - 1].length,
},
- Range,
+ }
MarkupKind,
- CompletionList,
+ ? className.__info.some((x) => x.__source === 'utilities')
MarkupKind,
-import type {
+ },
+ state.editor.capabilities.itemDefaults
+ )
}
function provideLayerDirectiveCompletions(
@@ -1239,47 +1265,103 @@ const match = text.match(/^\s*@layer\s+(?<partial>[^\s]*)$/i)
if (match === null) return null
+ return withDefaults(
+ {
import type {
- MarkupKind,
+import * as emmetHelper from 'vscode-emmet-helper-bundled'
Position,
+import { ensureArray } from './util/array'
+ Position,
import type {
- ) {
+ TextDocument,
Range,
- CompletionList,
+ MarkupKind,
+ sortText: naturalExpand(index, layers.length),
Range,
+ MarkupKind,
CompletionList,
+ MarkupKind,
import { Settings, State } from './util/state'
+ {
+ let testClass = beforeSlash + '/[0]'
Range,
+ TextDocument,
CompletionItem,
- CompletionItemKind,
+ MarkupKind,
- data: 'layer',
+ _type: 'layer',
- ...classListRange,
CompletionItem,
+ items: modifiers.map((modifier, index) => {
- Range,
+ }
CompletionItem,
+import type {
MarkupKind,
+ CompletionItemKind,
- ...classListRange,
+ }
CompletionItemKind,
+ }
Range,
+ },
+ end: position,
+ },
+ },
+ TextDocument,
Array.isArray(className.__info)
CompletionItem,
+ Position,
+}
+
+function withDefaults(
+ Position,
import * as jit from './util/jit'
+ Position,
import { getVariantsFromClassName } from './util/getVariantsFromClassName'
+ Position,
CompletionItem,
+ CompletionItemKind,
+): CompletionList {
+ if (modifiers) {
Range,
+ Position,
CompletionItem,
+ MarkupKind,
+
+import { docsUrl } from './util/docsUrl'
Position,
+ ...completionList,
+ ...(defaultData || defaultRange
+ ? {
+ itemDefaults: {
+ ...(defaultData && defaults.data ? { data: defaults.data } : {}),
+ ...(defaultRange && defaults.range ? { editRange: defaults.range } : {}),
},
+ }
+ : {}),
+ return {
CompletionItem,
- CompletionItem,
+ defaultData && defaultRange
+ return {
Range,
-import type {
+ return {
MarkupKind,
+ return {
CompletionList,
+ ...(defaultData || !defaults.data || item.data ? {} : { data: defaults.data }),
+ ...(defaultRange || !defaults.range
+ ? textEditText
+ ? { textEditText }
+ : {}
+import { Settings, State } from './util/state'
CompletionItem,
+ Range,
+ textEdit: {
+ newText: textEditText ?? item.label,
+ range: defaults.range,
+ CompletionItemKind,
items: modifiers.map((modifier, index) => {
+ Position,
Range,
- : className.__info.__source === 'utilities'
+ MarkupKind,
+ })),
}
}
@@ -1305,43 +1387,48 @@ const screens = dlv(state.config, ['screens'], dlv(state.config, ['theme', 'screens'], {}))
if (!isObject(screens)) return null
-import { docsUrl } from './util/docsUrl'
+ return withDefaults(
+ CompletionItem,
Position,
+import type {
import type {
- ) {
+import * as emmetHelper from 'vscode-emmet-helper-bundled'
+ items: Object.keys(screens).map((screen, index) => ({
+ Position,
Range,
- CompletionList,
Position,
Range,
- TextDocument,
+ MarkupKind,
Range,
-import * as culori from 'culori'
+ }
Range,
- TextDocument,
+ (context.triggerKind === 1 ||
+ MarkupKind,
import { Settings, State } from './util/state'
- ...classListRange,
CompletionItem,
+ }
+ let testClass = beforeSlash + '/[0]'
Range,
+ TextDocument,
- newText: screen,
+ _type: 'screen',
- Range,
CompletionItem,
- TextDocument,
+ items: modifiers.map((modifier, index) => {
- CompletionItem,
+ }
CompletionItem,
import type {
+ let { variants: existingVariants, offset } = getVariantsFromClassName(state, partialClassName)
- line: position.line,
- let subset: any
Position,
import { getColor, getColorFromValue } from './util/color'
- Range,
-import { getVariantsFromClassName } from './util/getVariantsFromClassName'
+ }
Range,
},
+ end: position,
},
- })),
MarkupKind,
-import type {
+import { Settings, State } from './util/state'
+ state.editor.capabilities.itemDefaults
+ )
}
function provideCssDirectiveCompletions(
@@ -1448,47 +1535,50 @@ ]
: []),
]
-import { docsUrl } from './util/docsUrl'
+ return withDefaults(
+ CompletionItem,
Position,
+import type {
import type {
- CompletionList,
+import * as emmetHelper from 'vscode-emmet-helper-bundled'
+ }
+ ...item,
+ Position,
MarkupKind,
-import { naturalExpand } from './util/naturalExpand'
+import { Settings, State } from './util/state'
Range,
-import { getVariantsFromClassName } from './util/getVariantsFromClassName'
+ (context.triggerKind === 1 ||
MarkupKind,
-import * as semver from './util/semver'
+import { Settings, State } from './util/state'
- MarkupKind,
+ ? className.__info.some((x) => x.__source === 'utilities')
import type {
- MarkupKind,
- Range,
+ TextDocument,
CompletionItem,
- MarkupKind,
Range,
-let isUtil = (className) =>
- Range,
+ TextDocument,
CompletionItem,
- TextDocument,
+ MarkupKind,
-import { getVariantsFromClassName } from './util/getVariantsFromClassName'
+ items: modifiers.map((modifier, index) => {
import type {
CompletionItem,
- CompletionItem,
+ items: modifiers.map((modifier, index) => {
+ }
CompletionItem,
- MarkupKind,
import type {
- CompletionList,
+ let { variants: existingVariants, offset } = getVariantsFromClassName(state, partialClassName)
+ Position,
import { getColor, getColorFromValue } from './util/color'
- Range,
- CompletionItem,
+ items: modifiers.map((modifier, index) => {
CompletionItem,
- Range,
},
- CompletionItem,
Position,
+import { Settings, State } from './util/state'
MarkupKind,
- })),
+ },
MarkupKind,
-import type {
+import { Settings, State } from './util/state'
+ state.editor.capabilities.itemDefaults
+ )
}
async function provideConfigDirectiveCompletions(
@@ -1513,54 +1603,61 @@ let partial = match.groups.partial.slice(1) // remove quote
let valueBeforeLastSlash = partial.substring(0, partial.lastIndexOf('/'))
let valueAfterLastSlash = partial.substring(partial.lastIndexOf('/') + 1)
-import { docsUrl } from './util/docsUrl'
+ return withDefaults(
+ CompletionItem,
Position,
+import type {
import type {
- ) {
+import * as emmetHelper from 'vscode-emmet-helper-bundled'
+ Position,
MarkupKind,
- CompletionItem,
+ CompletionItemKind,
+ Position,
MarkupKind,
+ Range,
+ .map(([name, type]) => ({
+ Position,
MarkupKind,
- CompletionItem,
CompletionList,
+ Position,
MarkupKind,
- CompletionItem,
TextDocument,
+ Position,
MarkupKind,
- CompletionItem,
Position,
- let { variants: existingVariants, offset } = getVariantsFromClassName(state, partialClassName)
+ let className = `${beforeSlash}/${modifier}`
- textEdit: {
+ : undefined,
+ })),
MarkupKind,
- CompletionItemKind,
import { Settings, State } from './util/state'
+ {
+ let testClass = beforeSlash + '/[0]'
Range,
+ let testClass = beforeSlash + '/[0]'
MarkupKind,
- Range,
- CompletionItem,
+ Position,
CompletionList,
- TextDocument,
+import type {
CompletionItem,
- CompletionList,
Position,
MarkupKind,
- state: State,
+ }
CompletionItem,
- )?.[1].modifiers
- Array.isArray(className.__info)
import type {
+ let { variants: existingVariants, offset } = getVariantsFromClassName(state, partialClassName)
+ Position,
import { getColor, getColorFromValue } from './util/color'
- Range,
+ character: position.character - valueAfterLastSlash.length,
},
+ }
MarkupKind,
- CompletionItemKind,
CompletionItem,
+ Position,
MarkupKind,
- classListRange: Range,
MarkupKind,
- filter?: (item: CompletionItem) => boolean,
+import { Settings, State } from './util/state'
- })),
+ state.editor.capabilities.itemDefaults
- }
+ )
}
async function provideEmmetCompletions(
@@ -1662,30 +1760,37 @@ state: State,
item: CompletionItem
): Promise<CompletionItem> {
MarkupKind,
+ let subsetKey: string[] = []
Position,
+ let classListContainsModifiers = state.classList.some(
+ let className = `${beforeSlash}/${modifier}`
Range,
+ )
+ ) {
return item
}
- MarkupKind,
let className = `${beforeSlash}/${modifier}`
+ MarkupKind,
let screens = dlv(state.config, ['theme', 'screens'], dlv(state.config, ['screens'], {}))
if (!isObject(screens)) screens = {}
item.detail = stringifyScreen(screens[item.label] as Screen)
return item
}
+ Position,
CompletionList,
-import { Settings, State } from './util/state'
+ CompletionList,
+ if (item.data?.important) {
- MarkupKind,
Position,
- MarkupKind,
+ modifiers = state.classList.find(
}
+ let variants = item.data?.variants ?? []
if (state.jit) {
if (item.kind === 9) return item
if (item.detail && item.documentation) return item
- let { root, rules } = jit.generateRules(state, [item.data.join(state.separator)])
+ let { root, rules } = jit.generateRules(state, [[...variants, className].join(state.separator)])
if (rules.length === 0) return item
if (!item.detail) {
if (rules.length === 1) {
@@ -1703,15 +1808,16 @@ }
return item
}
- const className = dlv(state.classNames.classNames, [...item.data, '__info'])
+ const rules = dlv(state.classNames.classNames, [...variants, className, '__info'])
if (item.kind === 9) {
- item.detail = state.classNames.context[item.data[item.data.length - 1]].join(', ')
+ item.detail = state.classNames.context[className].join(', ')
} else {
- item.detail = await getCssDetail(state, className)
+ item.detail = await getCssDetail(state, rules)
if (!item.documentation) {
const settings = await state.editor.getConfiguration()
- // modifiers
+ Position,
TextDocument,
+ Range,
if (css) {
item.documentation = {
kind: 'markdown' as typeof MarkupKind.Markdown,