Skip to content

Commit

Permalink
add ability to merge arrays of objects when using extend
Browse files Browse the repository at this point in the history
  • Loading branch information
RobinMalfait committed Oct 29, 2020
1 parent 584316f commit f12e276
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 3 deletions.
72 changes: 71 additions & 1 deletion __tests__/resolveConfig.test.js
Expand Up @@ -810,7 +810,7 @@ test('theme values in the extend section can extend values that are depended on
})
})

test('theme values in the extend section are not deeply merged', () => {
test('theme values in the extend section are not deeply merged when they are simple arrays', () => {
const userConfig = {
theme: {
extend: {
Expand Down Expand Up @@ -856,6 +856,76 @@ test('theme values in the extend section are not deeply merged', () => {
})
})

test('theme values in the extend section are deeply merged, when they are arrays of objects', () => {
const userConfig = {
theme: {
extend: {
typography: {
ArrayArray: {
css: [{ a: { backgroundColor: 'red' } }, { a: { color: 'green' } }],
},
ObjectArray: {
css: { a: { backgroundColor: 'red' } },
},
ArrayObject: {
css: [{ a: { backgroundColor: 'red' } }, { a: { color: 'green' } }],
},
},
},
},
}

const defaultConfig = {
prefix: '-',
important: false,
separator: ':',
theme: {
typography: {
ArrayArray: {
css: [{ a: { underline: 'none' } }],
},
ObjectArray: {
css: [{ a: { underline: 'none' } }],
},
ArrayObject: {
css: { a: { underline: 'none' } },
},
},
},
variants: {},
}

const result = resolveConfig([userConfig, defaultConfig])

expect(result).toMatchObject({
prefix: '-',
important: false,
separator: ':',
theme: {
typography: {
ArrayArray: {
css: [
{ a: { underline: 'none' } },
{ a: { backgroundColor: 'red' } },
{ a: { color: 'green' } },
],
},
ObjectArray: {
css: [{ a: { underline: 'none' } }, { a: { backgroundColor: 'red' } }],
},
ArrayObject: {
css: [
{ a: { underline: 'none' } },
{ a: { backgroundColor: 'red' } },
{ a: { color: 'green' } },
],
},
},
},
variants: {},
})
})

test('the theme function can use a default value if the key is missing', () => {
const userConfig = {
theme: {
Expand Down
22 changes: 20 additions & 2 deletions src/util/resolveConfig.js
Expand Up @@ -7,6 +7,8 @@ import map from 'lodash/map'
import get from 'lodash/get'
import uniq from 'lodash/uniq'
import toPath from 'lodash/toPath'
import head from 'lodash/head'
import isPlainObject from 'lodash/isPlainObject'
import negateValue from './negateValue'
import { corePluginList } from '../corePluginList'
import configurePlugins from './configurePlugins'
Expand Down Expand Up @@ -67,8 +69,24 @@ function mergeThemes(themes) {
}
}

function mergeExtensionCustomizer(_merged, value) {
if (Array.isArray(value)) return value
function mergeExtensionCustomizer(merged, value) {
// When we have an array of objects, we do want to merge it
if (Array.isArray(merged) && isPlainObject(head(merged))) {
return merged.concat(value)
}

// When the incoming value is an array, and the existing config is an object, prepend the existing object
if (Array.isArray(value) && isPlainObject(head(value)) && isPlainObject(merged)) {
return [merged, ...value]
}

// Override arrays (for example for font-families, box-shadows, ...)
if (Array.isArray(value)) {
return value
}

// Execute default behaviour
return undefined
}

function mergeExtensions({ extend, ...theme }) {
Expand Down

0 comments on commit f12e276

Please sign in to comment.