Skip to content

Commit 5a63099

Browse files
committed
add the ability to deep merge extended configs
1 parent 3c9c46c commit 5a63099

File tree

2 files changed

+124
-8
lines changed

2 files changed

+124
-8
lines changed

__tests__/resolveConfig.test.js

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,55 @@ test('theme key is merged instead of replaced', () => {
229229
})
230230
})
231231

232+
test('theme key is deeply merged instead of replaced', () => {
233+
const userConfig = {
234+
theme: {
235+
extend: {
236+
colors: {
237+
grey: {
238+
darker: '#606f7b',
239+
dark: '#8795a1',
240+
},
241+
},
242+
},
243+
},
244+
}
245+
246+
const defaultConfig = {
247+
prefix: '-',
248+
important: false,
249+
separator: ':',
250+
theme: {
251+
colors: {
252+
grey: {
253+
grey: '#b8c2cc',
254+
light: '#dae1e7',
255+
lighter: '#f1f5f8',
256+
},
257+
},
258+
},
259+
}
260+
261+
const result = resolveConfig([userConfig, defaultConfig])
262+
263+
expect(result).toMatchObject({
264+
prefix: '-',
265+
important: false,
266+
separator: ':',
267+
theme: {
268+
colors: {
269+
grey: {
270+
darker: '#606f7b',
271+
dark: '#8795a1',
272+
grey: '#b8c2cc',
273+
light: '#dae1e7',
274+
lighter: '#f1f5f8',
275+
},
276+
},
277+
},
278+
})
279+
})
280+
232281
test('variants key is merged instead of replaced', () => {
233282
const userConfig = {
234283
variants: {
@@ -1779,6 +1828,70 @@ test('variants can be extended', () => {
17791828
})
17801829
})
17811830

1831+
test('extensions are applied in the right order', () => {
1832+
const userConfig = {
1833+
theme: {
1834+
extend: {
1835+
colors: {
1836+
grey: {
1837+
light: '#eee',
1838+
},
1839+
},
1840+
},
1841+
},
1842+
}
1843+
1844+
const otherConfig = {
1845+
theme: {
1846+
extend: {
1847+
colors: {
1848+
grey: {
1849+
light: '#ddd',
1850+
darker: '#111',
1851+
},
1852+
},
1853+
},
1854+
},
1855+
}
1856+
1857+
const anotherConfig = {
1858+
theme: {
1859+
extend: {
1860+
colors: {
1861+
grey: {
1862+
darker: '#222',
1863+
},
1864+
},
1865+
},
1866+
},
1867+
}
1868+
1869+
const defaultConfig = {
1870+
theme: {
1871+
colors: {
1872+
grey: {
1873+
light: '#ccc',
1874+
dark: '#333',
1875+
},
1876+
},
1877+
},
1878+
}
1879+
1880+
const result = resolveConfig([userConfig, otherConfig, anotherConfig, defaultConfig])
1881+
1882+
expect(result).toMatchObject({
1883+
theme: {
1884+
colors: {
1885+
grey: {
1886+
light: '#eee',
1887+
dark: '#333',
1888+
darker: '#111',
1889+
},
1890+
},
1891+
},
1892+
})
1893+
})
1894+
17821895
test('variant sort order can be customized', () => {
17831896
const userConfig = {
17841897
variantOrder: [

src/util/resolveConfig.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,23 @@ function mergeThemes(themes) {
6767
}
6868
}
6969

70+
function mergeExtensionCustomizer(_merged, value) {
71+
if (Array.isArray(value)) return value
72+
}
73+
7074
function mergeExtensions({ extend, ...theme }) {
7175
return mergeWith(theme, extend, (themeValue, extensions) => {
7276
// The `extend` property is an array, so we need to check if it contains any functions
7377
if (!isFunction(themeValue) && !some(extensions, isFunction)) {
74-
return {
75-
...themeValue,
76-
...Object.assign({}, ...extensions),
77-
}
78+
return mergeWith({}, themeValue, ...extensions, mergeExtensionCustomizer)
7879
}
7980

80-
return (resolveThemePath, utils) => ({
81-
...value(themeValue, resolveThemePath, utils),
82-
...Object.assign({}, ...extensions.map((e) => value(e, resolveThemePath, utils))),
83-
})
81+
return (resolveThemePath, utils) =>
82+
mergeWith(
83+
{},
84+
...[themeValue, ...extensions].map((e) => value(e, resolveThemePath, utils)),
85+
mergeExtensionCustomizer
86+
)
8487
})
8588
}
8689

0 commit comments

Comments
 (0)