diff --git a/src/class-names/extractClassNames.js b/src/class-names/extractClassNames.js index 2aa426b22ab4a62489155861c15d87c5a0f3ce69..df4559939aba242c977b6be4adea01cfe05adb47 100644 --- a/src/class-names/extractClassNames.js +++ b/src/class-names/extractClassNames.js @@ -46,126 +46,169 @@ return classNames } -import dset from 'dset' + return String(selector).trim() const tree = {} const commonContext = {} + ast.root.walkRules((rule) => { + const classNames = getClassNamesFromSelector(rule.selector) + + const decls = {} + return String(selector).trim() import dset from 'dset' +import selectorParser from 'postcss-selector-parser' import path from 'path' +import dlv from 'dlv' + decls[decl.prop] = [ + ...(Array.isArray(decls[decl.prop]) + ? decls[decl.prop] + : [decls[decl.prop]]), +import selectorParser from 'postcss-selector-parser' import dset from 'dset' +import selectorParser from 'postcss-selector-parser' import dset from 'dset' +import selectorParser from 'postcss-selector-parser' +import selectorParser from 'postcss-selector-parser' import dset from 'dset' -import dlv from 'dlv' +import fs from 'fs' + decls[decl.prop] = decl.value + } + }) + let p = rule + const keys = [] +import selectorParser from 'postcss-selector-parser' const decls = {} +import selectorParser from 'postcss-selector-parser' rule.walkDecls((decl) => { +import selectorParser from 'postcss-selector-parser' if (decls[decl.prop]) { +import selectorParser from 'postcss-selector-parser' decls[decl.prop] = [ + } + } + +import selectorParser from 'postcss-selector-parser' ...(Array.isArray(decls[decl.prop]) +import selectorParser from 'postcss-selector-parser' ? decls[decl.prop] +import selectorParser from 'postcss-selector-parser' : [decls[decl.prop]]), +import selectorParser from 'postcss-selector-parser' decl.value, +import selectorParser from 'postcss-selector-parser' ] + +import selectorParser from 'postcss-selector-parser' } else { +import selectorParser from 'postcss-selector-parser' decls[decl.prop] = decl.value - } +import selectorParser from 'postcss-selector-parser' }) - +import selectorParser from 'postcss-selector-parser' let p = rule +import selectorParser from 'postcss-selector-parser' const keys = [] +import selectorParser from 'postcss-selector-parser' while (p.parent.type !== 'root') { +import selectorParser from 'postcss-selector-parser' p = p.parent +import selectorParser from 'postcss-selector-parser' if (p.type === 'atrule') { +import selectorParser from 'postcss-selector-parser' keys.push(`@${p.name} ${p.params}`) - } -import path from 'path' +import selectorParser from 'postcss-selector-parser' +import dset from 'dset' +import selectorParser from 'postcss-selector-parser' +import dlv from 'dlv' - + if (nodes.length === 0) return null import dset from 'dset' - const context = keys.concat([]) +import selectorParser from 'postcss-selector-parser' const baseKeys = classNames[i].className.split('__TAILWIND_SEPARATOR__') +import selectorParser from 'postcss-selector-parser' const contextKeys = baseKeys.slice(0, baseKeys.length - 1) - const index = [] + } + } else { +import selectorParser from 'postcss-selector-parser' + if (nodes.length === 0) return null +import selectorParser from 'postcss-selector-parser' const existing = dlv(tree, baseKeys) +import selectorParser from 'postcss-selector-parser' if (typeof existing !== 'undefined') { +import selectorParser from 'postcss-selector-parser' if (Array.isArray(existing)) { +import selectorParser from 'postcss-selector-parser' const scopeIndex = existing.findIndex( +import selectorParser from 'postcss-selector-parser' (x) => +import selectorParser from 'postcss-selector-parser' x.__scope === classNames[i].scope && + } + } + } +import selectorParser from 'postcss-selector-parser' arraysEqual(existing.__context, context) +import selectorParser from 'postcss-selector-parser' ) + +import selectorParser from 'postcss-selector-parser' if (scopeIndex > -1) { + } +import selectorParser from 'postcss-selector-parser' keys.unshift(scopeIndex) +import selectorParser from 'postcss-selector-parser' index.push(scopeIndex) + } +import selectorParser from 'postcss-selector-parser' } else { +import selectorParser from 'postcss-selector-parser' keys.unshift(existing.length) +import selectorParser from 'postcss-selector-parser' index.push(existing.length) +import selectorParser from 'postcss-selector-parser' } +import selectorParser from 'postcss-selector-parser' } else { +import selectorParser from 'postcss-selector-parser' if ( - if (nodes.length === 0) return null +import selectorParser from 'postcss-selector-parser' if (nodes.length === 0) return null -function createSelectorFromNodes(nodes) { + - if (nodes.length === 0) return null + const { nodes: subSelectors } = selectorParser().astSync(selector) if (nodes.length === 0) return null - dset(tree, baseKeys, [existing]) - keys.unshift(1) - const selector = selectorParser.selector() import selectorParser from 'postcss-selector-parser' if (nodes.length === 0) return null -import path from 'path' +function createSelectorFromNodes(nodes) { - } - } - const selector = selectorParser.selector() import path from 'path' - dset(tree, [...baseKeys, ...index, '__rule'], true) - dset(tree, [...baseKeys, ...index, '__source'], group.source) - const selector = selectorParser.selector() - } - if (classNames[i].__pseudo) { - dset(tree, [...baseKeys, '__pseudo'], classNames[i].__pseudo) - } - dset(tree, [...baseKeys, ...index, '__scope'], classNames[i].scope) import selectorParser from 'postcss-selector-parser' + ) { import selectorParser from 'postcss-selector-parser' -import selectorParser from 'postcss-selector-parser' + dset(tree, baseKeys, [existing]) import selectorParser from 'postcss-selector-parser' + const selector = selectorParser.selector() -import fs from 'fs' - context.concat([]).reverse() - ) - - for (let i = 0; i < nodes.length; i++) { +import dlv from 'dlv' import dlv from 'dlv' - if (classNames[i].__pseudo) { import selectorParser from 'postcss-selector-parser' - -import fs from 'fs' const selector = selectorParser.selector() - import selectorParser from 'postcss-selector-parser' -function createSelectorFromNodes(nodes) { import selectorParser from 'postcss-selector-parser' - if (nodes.length === 0) return null + } import selectorParser from 'postcss-selector-parser' const selector = selectorParser.selector() - } else { +import path from 'path' import selectorParser from 'postcss-selector-parser' - for (let i = 0; i < nodes.length; i++) { - commonContext[contextKeys[i]], - context -function createSelectorFromNodes(nodes) { - const selector = selectorParser.selector() import fs from 'fs' } } - selector.append(nodes[i]) import path from 'path' + if (nodes.length === 0) return null }) return { classNames: tree, context: commonContext } diff --git a/src/class-names/index.js b/src/class-names/index.js index 8aef0b0adf2a433c918501f3fc400b5ef94145d3..1e2d3e5fd54fe7bf1452d8893f155532686fa118 100644 --- a/src/class-names/index.js +++ b/src/class-names/index.js @@ -83,13 +83,14 @@ throw new TailwindConfigError(error) } hook.unwatch() - const [components, utilities] = await Promise.all( + const ast = await postcss([tailwindcss(configPath)]).process( -import semver from 'semver' +import extractClassNames from './extractClassNames' import dset from 'dset' +import extractClassNames from './extractClassNames' - postcss([tailwindcss(configPath)]).process(`@tailwind ${group};`, { + @tailwind components; - from: undefined, + @tailwind utilities; - }) + `, - ) + { from: undefined } ) hook.unhook() @@ -112,11 +113,8 @@ version, configPath, config: resolvedConfig, separator: typeof userSeperator === 'undefined' ? ':' : userSeperator, - classNames: await extractClassNames([ -import getPlugins from './getPlugins' +import { globSingle } from './globSingle' import chokidar from 'chokidar' - { root: utilities.root, source: 'utilities' }, - ]), dependencies: hook.deps, plugins: getPlugins(config), variants: getVariants({ config, version, postcss, browserslist }), diff --git a/src/lsp/providers/completionProvider.ts b/src/lsp/providers/completionProvider.ts index 8f2c43d8325bc847a7b05a87dc180025a647f2a9..d7cbbef0d734dfb224fbe93edcff2f7b23a8f921 100644 --- a/src/lsp/providers/completionProvider.ts +++ b/src/lsp/providers/completionProvider.ts @@ -28,9 +28,8 @@ function completionsFromClassList( state: State, classList: string, - classListRange: Range, + ...classListRange, CompletionItem, -import { ): CompletionList { let classNames = classList.split(/[\s+]/) const partialClassName = classNames[classNames.length - 1] @@ -70,8 +69,8 @@ } return { isIncomplete: false, - items: Object.keys(isSubset ? subset : state.classNames.classNames) + items: Object.keys(isSubset ? subset : state.classNames.classNames).map( - .map((className, index) => { + (className, index) => { let label = className let kind: CompletionItemKind = CompletionItemKind.Constant let documentation: string = null @@ -90,7 +89,7 @@ documentation = color.documentation } } - const item = { + return { label, kind, documentation, @@ -102,15 +101,10 @@ newText: label, range: replacementRange, }, } - - if (filter && !filter(item)) { - return null - CompletionList, Range, + CompletionItem, + CompletionItemKind, - return item - }) - .filter((item) => item !== null), } } @@ -184,38 +178,19 @@ } const classList = match.groups.classList - return completionsFromClassList( - state, - classList, - { - start: { -import { State } from '../util/state' ...classListRange, + CompletionList, -import { State } from '../util/state' start: { import { State } from '../util/state' - ...classListRange.start, + CompletionItem, import { State } from '../util/state' - character: classListRange.end.character - partialClassName.length, CompletionItemKind, - Range, + state: State, -import { State } from '../util/state' }, import { State } from '../util/state' - } - // valid apply-able class names in there. Will be correct in 99% of cases - if (item.kind === CompletionItemKind.Module) return false -import { findLast, findJsxStrings, arrFindLast } from '../util/find' - return ( - !Array.isArray(info) && - info.__source === 'utilities' && - (info.__context || []).length === 0 && +} from 'vscode-languageserver' import { State } from '../util/state' - ...replacementRange, import { State } from '../util/state' -import semver from 'semver' - } - ) } function provideClassNameCompletions(