-
Notifications
You must be signed in to change notification settings - Fork 6
/
convertStyle.js
48 lines (41 loc) · 1.8 KB
/
convertStyle.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import getType from 'jest-get-type';
export function containsRvh(propertyValue) {
// TODO: when regexp is lifted up the lexical scope, to be used
// in both `containsRvh` and `replaceRvhWithPx`, some tests start to
// fail. Seems like a regexp object contains some weird state that
// changes after executions; executions interfere with each other.
// It would be nice to figure out what is the problem exactly.
const rvhRegex = /(\d+(\.\d*)?)rvh(?!\w)/;
return rvhRegex.test(propertyValue);
}
function replaceRvhWithPx(propertyStringValue, windowHeight) {
// regexp is global to make #replace work multiple times
const rvhRegex = /(\d+(\.\d*)?)rvh(?!\w)/g;
return propertyStringValue.replace(
rvhRegex,
(_, rvh) => `${(windowHeight * parseFloat(rvh)) / 100}px`
);
}
function throwOnBadArgs(givenStyle, windowHeight) {
if (getType(givenStyle) !== 'object' && givenStyle !== undefined)
throw Error(`style (the first argument) must be an object or undefined`);
if (typeof windowHeight !== 'number' || windowHeight < 0)
throw Error('Second argument (windowHeight) must be a non-negative number');
}
function convertStyle(givenStyle, windowHeight) {
throwOnBadArgs(givenStyle, windowHeight);
// If style is not passed, implicit {height: '100rvh'} style is used.
const defaultStyle = { height: '100rvh' };
const usedStyle = givenStyle === undefined ? defaultStyle : givenStyle;
const convertedStyle = {};
Object.keys(usedStyle).forEach(key => {
// if a value contains no rvh unit, it's used as is, otherwise converted
// to px; 1rvh = (window.innerHeight / 100)px
convertedStyle[key] =
typeof usedStyle[key] === 'string'
? replaceRvhWithPx(usedStyle[key], windowHeight)
: usedStyle[key];
});
return convertedStyle;
}
export default convertStyle;