-
Notifications
You must be signed in to change notification settings - Fork 0
/
mod.ts
59 lines (54 loc) · 1.45 KB
/
mod.ts
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
49
50
51
52
53
54
55
56
57
58
59
const PARENT_CHAR = '&';
interface Prop {
[key: string]: Prop | string | number;
}
/**
* Return the kebab case syntax from a string.
* @param str The string.
* @return Kebab case string.
*/
function kebabCase(str: string) {
return (str.match(/(?:[A-Z0-9]+|(?:[A-Z]?[a-z0-9]+))(?=[A-Z _-]|\b)/g) || [])
.join('-')
.toLowerCase();
}
/**
* Return a reduced object from an array.
* @param array The array.
* @param fn The function that return an object for each value / index.
* @return Resulted object.
*/
function array2object<T, U extends object>(array: T[], fn: (value: T, index: number) => U) {
return array.reduce((acc, a, i) => ({
...acc,
...fn(a, i),
}),
{} as U);
}
/**
* Return a css string from an object.
* @param obj The object.
* @return Css string.
*/
function object2css(obj: Record<string, Prop>) {
let css = '';
for (const selector in obj) {
const subSelectors: Record<string, Prop>[] = [];
css += `${selector}{`;
for (const prop in obj[selector]) {
const value = obj[selector][prop];
if (typeof value === 'object') {
const p = prop[0] === PARENT_CHAR ? `${selector}${prop.slice(1)}` : `${selector} ${prop}`;
subSelectors.push({ [p]: value });
} else {
css += `${kebabCase(prop)}:${value};`;
}
}
css += '}';
for (const k in subSelectors) {
css += object2css(subSelectors[k]);
}
}
return css;
}
export { kebabCase, array2object, object2css };