Skip to content

Commit eac64d8

Browse files
committed
fix(plugin-theme-value): support numeric keys, return correctly negated value
- add tests. - numeric keys were not supported in previous implementation. - negated value was always negating as a string type. Preserve the original numeric type if identified. - cleanup formatting in relating files.
1 parent 37e95c7 commit eac64d8

File tree

4 files changed

+140
-10
lines changed

4 files changed

+140
-10
lines changed

cypress/tests/components/element.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ describe('Element', () => {
3838
.should('have.prop', 'href', 'https://uinix.dev/');
3939
});
4040

41-
it.only('should render as the specified custom element passing through Element props', () => {
41+
it('should render as the specified custom element passing through Element props', () => {
4242
const CustomElement = ({x, ...rest}) => (
4343
<Element as="a" {...rest}>
4444
Custom Element: {x}
Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,129 @@
1-
import {themeValue} from '../../../lib/renderer/plugin-theme-value.js';
1+
import {
2+
_resolveThemeValues as resolveThemeValues,
3+
themeValue,
4+
} from '../../../lib/renderer/plugin-theme-value.js';
25

36
describe('themeValue', () => {
47
it('should not throw when initialized', () => {
58
expect(() => themeValue()).to.not.throw();
69
});
710

811
it('is tested in system/theme/', () => {});
12+
13+
describe('resolveThemeValues', () => {
14+
it('should return themed style if values do not exist in theme', () => {
15+
const style = {
16+
backgroundColor: 'blue',
17+
padding: 9999,
18+
};
19+
20+
const theme = {
21+
colors: {
22+
primary: 'red',
23+
},
24+
spacings: {
25+
m: 42,
26+
},
27+
};
28+
29+
expect(resolveThemeValues(style, theme)).to.deep.equal({
30+
backgroundColor: 'blue',
31+
padding: 9999,
32+
});
33+
});
34+
35+
it('should resolve a themed style based on provided theme', () => {
36+
const style = {
37+
backgroundColor: 'brand',
38+
padding: 'm',
39+
};
40+
41+
const theme = {
42+
colors: {
43+
brand: 'red',
44+
},
45+
spacings: {
46+
m: 42,
47+
},
48+
};
49+
50+
expect(resolveThemeValues(style, theme)).to.deep.equal({
51+
backgroundColor: 'red',
52+
padding: 42,
53+
});
54+
});
55+
56+
it('should resolve a themed style with nested theme property keys', () => {
57+
const style = {
58+
backgroundColor: 'brand.primary',
59+
padding: 'large.m',
60+
};
61+
62+
const theme = {
63+
colors: {
64+
brand: {
65+
primary: 'red',
66+
},
67+
},
68+
spacings: {
69+
large: {
70+
m: 42,
71+
},
72+
},
73+
};
74+
75+
expect(resolveThemeValues(style, theme)).to.deep.equal({
76+
backgroundColor: 'red',
77+
padding: 42,
78+
});
79+
});
80+
81+
it('should resolve a negative theme values', () => {
82+
const style = {
83+
margin: '-m',
84+
padding: '-large.m',
85+
};
86+
87+
const theme = {
88+
spacings: {
89+
m: '42px',
90+
large: {
91+
m: 9999,
92+
},
93+
},
94+
};
95+
96+
expect(resolveThemeValues(style, theme)).to.deep.equal({
97+
margin: '-42px',
98+
padding: -9999,
99+
});
100+
});
101+
102+
it('should resolve a themed style with numeric theme property keys', () => {
103+
const style = {
104+
marginLeft: 2,
105+
marginRight: -2,
106+
marginTop: 'large.2',
107+
marginBottom: '-large.2',
108+
margin: -1234,
109+
};
110+
111+
const theme = {
112+
spacings: {
113+
2: '42px',
114+
large: {
115+
2: 9999,
116+
},
117+
},
118+
};
119+
120+
expect(resolveThemeValues(style, theme)).to.deep.equal({
121+
marginLeft: '42px',
122+
marginRight: '-42px',
123+
marginTop: 9999,
124+
marginBottom: -9999,
125+
margin: -1234,
126+
});
127+
});
128+
});
9129
});

lib/renderer/plugin-theme-value.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {isPlainObject, props} from 'uinix-fp';
22
import {themeMapping} from 'uinix-theme';
33

44
export {themeValue};
5+
export {resolveThemeValues as _resolveThemeValues};
56

67
/**
78
* @typedef {import('fela').IStyle} IStyle
@@ -51,22 +52,29 @@ const resolveThemeValues = (style, theme) => {
5152
const NEGATIVE_REGEXP = /^\s*-/;
5253
const mapping = createThemeMapping(themeMapping);
5354

54-
Object.entries(style).forEach(([property, value]) => {
55+
Object.entries(style).forEach(([property, styleValue]) => {
5556
const resolveThemeValue = mapping[property];
56-
if (resolveThemeValue && typeof value === 'string') {
57-
const isNegative = NEGATIVE_REGEXP.test(value);
57+
if (resolveThemeValue) {
58+
const isNegative = NEGATIVE_REGEXP.test(styleValue);
5859
if (isNegative) {
59-
value = value.split(NEGATIVE_REGEXP)[1].trim();
60+
styleValue = String(styleValue).split(NEGATIVE_REGEXP)[1].trim();
6061
}
6162

62-
const themeValue = props(value)(resolveThemeValue(theme)) || value;
63+
const resolvedValue =
64+
props(String(styleValue))(resolveThemeValue(theme)) || styleValue;
65+
const isNumber = !Number.isNaN(Number(resolvedValue));
6366
// @ts-ignore: we CAN access from IStyle
64-
style[property] = isNegative ? `-${themeValue}` : themeValue;
65-
} else if (isPlainObject(value)) {
67+
style[property] = isNegative
68+
? isNumber
69+
? -resolvedValue
70+
: `-${resolvedValue}`
71+
: resolvedValue;
72+
} else if (isPlainObject(styleValue)) {
6673
// @ts-ignore: we CAN access from IStyle
6774
style[property] = resolveThemeValues(style[property], theme);
6875
}
6976
});
77+
7078
return style;
7179
};
7280

lib/util/parse-svg-element.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import {toH} from 'hast-to-hyperscript';
22
import {parse} from 'svg-parser';
33

4+
export {parseSvgElement};
5+
46
/**
57
* @typedef {import('../types.js').H} H
68
*/
@@ -13,7 +15,7 @@ import {parse} from 'svg-parser';
1315
* @param {string} [options.svg]
1416
* @returns {ReturnType<H>|null}
1517
*/
16-
export const parseSvgElement = ({h, svg}) => {
18+
const parseSvgElement = ({h, svg}) => {
1719
if (!svg) {
1820
return null;
1921
}

0 commit comments

Comments
 (0)