/
object.ts
110 lines (95 loc) · 3.05 KB
/
object.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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import type { CSSEntries, CSSObject, CSSValue, DeepPartial, Rule, Shortcut, StaticRule, StaticShortcut } from '../types'
import { isString } from './basic'
export function normalizeCSSEntries(obj: string | CSSEntries | CSSObject): string | CSSEntries {
if (isString(obj))
return obj
return (!Array.isArray(obj) ? Object.entries(obj) : obj).filter(i => i[1] != null)
}
export function normalizeCSSValues(obj: CSSValue | string | (CSSValue | string)[]): (string | CSSEntries)[] {
if (Array.isArray(obj)) {
// @ts-expect-error type cast
if (obj.find(i => !Array.isArray(i) || Array.isArray(i[0])))
return (obj as (string | CSSValue)[]).map(i => normalizeCSSEntries(i))
else
return [obj as CSSEntries]
}
else {
return [normalizeCSSEntries(obj)]
}
}
export function clearIdenticalEntries(entry: CSSEntries): CSSEntries {
return entry.filter(([k, v], idx) => {
// remove control keys
if (k.startsWith('$$'))
return false
// remove identical entries
for (let i = idx - 1; i >= 0; i--) {
if (entry[i][0] === k && entry[i][1] === v)
return false
}
return true
})
}
export function entriesToCss(arr?: CSSEntries) {
if (arr == null)
return ''
return clearIdenticalEntries(arr)
.map(([key, value]) => value != null ? `${key}:${value};` : undefined)
.filter(Boolean)
.join('')
}
export function isObject(item: any): item is Record<string, any> {
return (item && typeof item === 'object' && !Array.isArray(item))
}
export function mergeDeep<T>(original: T, patch: DeepPartial<T>): T {
const o = original as any
const p = patch as any
if (Array.isArray(o) && Array.isArray(p))
return [...o, ...p] as any
if (Array.isArray(o))
return [...o] as any
const output = { ...o }
if (isObject(o) && isObject(p)) {
Object.keys(p).forEach((key) => {
if ((isObject(o[key]) && isObject(p[key])) || (Array.isArray(o[key]) && Array.isArray(p[key])))
output[key] = mergeDeep(o[key], p[key])
else
Object.assign(output, { [key]: p[key] })
})
}
return output
}
export function clone<T>(val: T): T {
let k: any, out: any, tmp: any
if (Array.isArray(val)) {
out = Array(k = val.length)
// eslint-disable-next-line no-cond-assign
while (k--) out[k] = (tmp = val[k]) && typeof tmp === 'object' ? clone(tmp) : tmp
return out as any
}
if (Object.prototype.toString.call(val) === '[object Object]') {
out = {} // null
for (k in val) {
if (k === '__proto__') {
Object.defineProperty(out, k, {
value: clone((val as any)[k]),
configurable: true,
enumerable: true,
writable: true,
})
}
else {
// eslint-disable-next-line no-cond-assign
out[k] = (tmp = (val as any)[k]) && typeof tmp === 'object' ? clone(tmp) : tmp
}
}
return out
}
return val
}
export function isStaticRule(rule: Rule): rule is StaticRule {
return isString(rule[0])
}
export function isStaticShortcut(sc: Shortcut): sc is StaticShortcut {
return isString(sc[0])
}