diff --git a/packages/preset-mini/src/utils/utilities.ts b/packages/preset-mini/src/utils/utilities.ts index 7ac7b8c482..30dac481f9 100644 --- a/packages/preset-mini/src/utils/utilities.ts +++ b/packages/preset-mini/src/utils/utilities.ts @@ -23,10 +23,27 @@ export const directionSize = (propertyPrefix: string) => ([_, direction, size]: /** * Obtain color from theme by camel-casing colors. */ -const getThemeColor = (theme: Theme, colors: string[]) => - theme.colors?.[ - colors.join('-').replace(/(-[a-z])/g, n => n.slice(1).toUpperCase()) - ] +const getThemeColor = (theme: Theme, colors: string[]) => { + let obj: Theme['colors'] | string = theme.colors + let index = -1 + + for (const c of colors) { + index += 1 + if (obj && typeof obj !== 'string') { + const camel = colors.slice(index).join('-').replace(/(-[a-z])/g, n => n.slice(1).toUpperCase()) + if (obj[camel]) + return obj[camel] + + if (obj[c]) { + obj = obj[c] + continue + } + } + return undefined + } + + return obj +} /** * Parse color string into {@link ParsedColorValue} (if possible). Color value will first be matched to theme object before parsing. @@ -81,6 +98,10 @@ export const parseColor = (body: string, theme: Theme): ParsedColorValue | undef if (scale.match(/^\d+$/)) { no = scale colorData = getThemeColor(theme, colors.slice(0, -1)) + if (!colorData || typeof colorData === 'string') + color = undefined + else + color = colorData[no] as string } else { colorData = getThemeColor(theme, colors) @@ -88,12 +109,11 @@ export const parseColor = (body: string, theme: Theme): ParsedColorValue | undef [, no = no] = colors colorData = getThemeColor(theme, [name]) } + if (typeof colorData === 'string') + color = colorData + else if (no && colorData) + color = colorData[no] as string } - - if (typeof colorData === 'string') - color = colorData - else if (no && colorData) - color = colorData[no] } return { diff --git a/test/__snapshots__/preset-mini.test.ts.snap b/test/__snapshots__/preset-mini.test.ts.snap index 3ea116cdd5..d59156ad4a 100644 --- a/test/__snapshots__/preset-mini.test.ts.snap +++ b/test/__snapshots__/preset-mini.test.ts.snap @@ -7,6 +7,13 @@ exports[`preset-mini > custom var prefix 1`] = ` .scale-100{--hi-scale-x:1;--hi-scale-y:1;transform:translateX(var(--hi-translate-x)) translateY(var(--hi-translate-y)) translateZ(var(--hi-translate-z)) rotate(var(--hi-rotate)) rotateX(var(--hi-rotate-x)) rotateY(var(--hi-rotate-y)) rotateZ(var(--hi-rotate-z)) skewX(var(--hi-skew-x)) skewY(var(--hi-skew-y)) scaleX(var(--hi-scale-x)) scaleY(var(--hi-scale-y)) scaleZ(var(--hi-scale-z));}" `; +exports[`preset-mini > nested theme colors 1`] = ` +"/* layer: default */ +.bg-a-b-c{--un-bg-opacity:1;background-color:rgba(81,69,67,var(--un-bg-opacity));} +.text-a-b-c{--un-text-opacity:1;color:rgba(81,69,67,var(--un-text-opacity));} +.text-a-camel-case{--un-text-opacity:1;color:rgba(34,51,68,var(--un-text-opacity));}" +`; + exports[`preset-mini > targets 1`] = ` "/* layer: preflights */ *,::before,::after{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-ring-offset-shadow:0 0 rgba(0,0,0,0);--un-ring-shadow:0 0 rgba(0,0,0,0);--un-shadow-inset: ;--un-shadow:0 0 rgba(0,0,0,0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,0.5);}::backdrop{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-ring-offset-shadow:0 0 rgba(0,0,0,0);--un-ring-shadow:0 0 rgba(0,0,0,0);--un-shadow-inset: ;--un-shadow:0 0 rgba(0,0,0,0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,0.5);} diff --git a/test/preset-mini.test.ts b/test/preset-mini.test.ts index 3ef92d5b71..4b713fb850 100644 --- a/test/preset-mini.test.ts +++ b/test/preset-mini.test.ts @@ -16,6 +16,12 @@ const uno = createGenerator({ a: 'var(--custom)', b: 'rgba(var(--custom), %alpha)', }, + a: { + b: { + c: '#514543', + }, + camelCase: '#234', + }, }, }, }) @@ -62,6 +68,17 @@ describe('preset-mini', () => { expect(css).toMatchSnapshot() }) + test('nested theme colors', async () => { + const { css, matched } = await uno.generate([ + 'text-a-b-c', + 'text-a-camel-case', + 'bg-a-b-c', + ], { preflights: false }) + + expect(css).toMatchSnapshot('') + expect(matched.size).toBe(3) + }) + test('none targets', async () => { const { css, matched } = await uno.generate(new Set(presetMiniNonTargets), { minify: true, preflights: false })