From 95b249409b8165bc8e36478f523295e6dd0d32f0 Mon Sep 17 00:00:00 2001 From: Brad Cornes Date: Sat, 2 May 2020 13:18:30 +0100 Subject: [PATCH] support css properties with multiple values --- .../src/extractClassNames.mjs | 11 +++++++++- .../tests/extractClassNames.test.js | 21 +++++++++++++++++++ .../src/providers/completionProvider.ts | 18 ++++++++++++---- .../src/util/array.ts | 11 ++++++++++ .../src/util/stringify.ts | 8 ++++--- 5 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 packages/tailwindcss-language-server/src/util/array.ts diff --git a/packages/tailwindcss-class-names/src/extractClassNames.mjs b/packages/tailwindcss-class-names/src/extractClassNames.mjs index 4ccb662..df45599 100644 --- a/packages/tailwindcss-class-names/src/extractClassNames.mjs +++ b/packages/tailwindcss-class-names/src/extractClassNames.mjs @@ -55,7 +55,16 @@ async function process(ast) { const decls = {} rule.walkDecls((decl) => { - decls[decl.prop] = decl.value + if (decls[decl.prop]) { + decls[decl.prop] = [ + ...(Array.isArray(decls[decl.prop]) + ? decls[decl.prop] + : [decls[decl.prop]]), + decl.value, + ] + } else { + decls[decl.prop] = decl.value + } }) let p = rule diff --git a/packages/tailwindcss-class-names/tests/extractClassNames.test.js b/packages/tailwindcss-class-names/tests/extractClassNames.test.js index 7e7b647..fe8e04b 100644 --- a/packages/tailwindcss-class-names/tests/extractClassNames.test.js +++ b/packages/tailwindcss-class-names/tests/extractClassNames.test.js @@ -350,3 +350,24 @@ test('processes multiple scopes for the same class name', async () => { }, }) }) + +test('processes multiple properties of the same name', async () => { + const result = await processCss(` + .bg-red { + background-color: blue; + background-color: red; + } + `) + + expect(result).toEqual({ + context: {}, + classNames: { + 'bg-red': { + __rule: true, + __context: [], + __scope: null, + 'background-color': ['blue', 'red'], + }, + }, + }) +}) diff --git a/packages/tailwindcss-language-server/src/providers/completionProvider.ts b/packages/tailwindcss-language-server/src/providers/completionProvider.ts index 54f3907..bb78423 100644 --- a/packages/tailwindcss-language-server/src/providers/completionProvider.ts +++ b/packages/tailwindcss-language-server/src/providers/completionProvider.ts @@ -23,6 +23,7 @@ import { isJsContext } from '../util/js' import { naturalExpand } from '../util/naturalExpand' import semver from 'semver' import { docsUrl } from '../util/docsUrl' +import { ensureArray } from '../util/array' function completionsFromClassList( state: State, @@ -725,10 +726,19 @@ function isContextItem(state: State, keys: string[]): boolean { } function stringifyDecls(obj: any): string { - return Object.keys(obj) - .map((prop) => { - return `${prop}: ${obj[prop]};` - }) + let props = Object.keys(obj) + let nonCustomProps = props.filter((prop) => !prop.startsWith('--')) + + if (props.length !== nonCustomProps.length && nonCustomProps.length !== 0) { + props = nonCustomProps + } + + return props + .map((prop) => + ensureArray(obj[prop]) + .map((value) => `${prop}: ${value};`) + .join(' ') + ) .join(' ') } diff --git a/packages/tailwindcss-language-server/src/util/array.ts b/packages/tailwindcss-language-server/src/util/array.ts new file mode 100644 index 0000000..13683cc --- /dev/null +++ b/packages/tailwindcss-language-server/src/util/array.ts @@ -0,0 +1,11 @@ +export function dedupe(arr: Array): Array { + return arr.filter((value, index, self) => self.indexOf(value) === index) +} + +export function ensureArray(value: T | T[]): T[] { + return Array.isArray(value) ? value : [value] +} + +export function flatten(arrays: T[][]): T[] { + return [].concat.apply([], arrays) +} diff --git a/packages/tailwindcss-language-server/src/util/stringify.ts b/packages/tailwindcss-language-server/src/util/stringify.ts index 5433e90..f2811a6 100644 --- a/packages/tailwindcss-language-server/src/util/stringify.ts +++ b/packages/tailwindcss-language-server/src/util/stringify.ts @@ -1,6 +1,7 @@ import removeMeta from './removeMeta' const dlv = require('dlv') import escapeClassName from 'css.escape' +import { ensureArray } from './array' export function stringifyConfigValue(x: any): string { if (typeof x === 'string') return x @@ -35,9 +36,10 @@ export function stringifyCss(className: string, obj: any): string { const indentStr = '\t'.repeat(context.length) const decls = props.reduce((acc, curr, i) => { - return `${acc}${i === 0 ? '' : '\n'}${indentStr + '\t'}${curr}: ${ - obj[curr] - };` + const propStr = ensureArray(obj[curr]) + .map((val) => `${indentStr + '\t'}${curr}: ${val};`) + .join('\n') + return `${acc}${i === 0 ? '' : '\n'}${propStr}` }, '') css += `${indentStr}${augmentClassName( className,