forked from babel/website
/
ASTUtils.js
132 lines (114 loc) · 3.47 KB
/
ASTUtils.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
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// https://github.com/hughsk/flat/blob/master/index.js
function isBuffer(obj) {
return (
obj != null &&
obj.constructor != null &&
typeof obj.constructor.isBuffer === "function" &&
obj.constructor.isBuffer(obj)
);
}
function flatten(target, opts) {
opts = opts || {};
const delimiter = opts.delimiter || ".";
const maxDepth = opts.maxDepth;
const output = {};
function step(object, prev, currentDepth) {
currentDepth = currentDepth || 1;
Object.keys(object).forEach(function(key) {
const value = object[key];
const isarray = opts.safe && Array.isArray(value);
const type = Object.prototype.toString.call(value);
const isbuffer = isBuffer(value);
const isobject = type === "[object Object]" || type === "[object Array]";
const newKey = prev ? prev + delimiter + key : key;
if (
!isarray &&
!isbuffer &&
isobject &&
Object.keys(value).length &&
(!opts.maxDepth || currentDepth < maxDepth)
) {
return step(value, newKey, currentDepth + 1);
}
output[newKey] = value;
});
}
step(target);
return output;
}
function unflatten(target, opts) {
opts = opts || {};
const delimiter = opts.delimiter || ".";
const overwrite = opts.overwrite || false;
const result = {};
const isbuffer = isBuffer(target);
if (
isbuffer ||
Object.prototype.toString.call(target) !== "[object Object]"
) {
return target;
}
// safely ensure that the key is
// an integer.
function getkey(key) {
const parsedKey = Number(key);
return isNaN(parsedKey) || key.indexOf(".") !== -1 || opts.object
? key
: parsedKey;
}
const sortedKeys = Object.keys(target).sort(function(keyA, keyB) {
return keyA.length - keyB.length;
});
sortedKeys.forEach(function(key) {
const split = key.split(delimiter);
let key1 = getkey(split.shift());
let key2 = getkey(split[0]);
let recipient = result;
while (key2 !== undefined) {
const type = Object.prototype.toString.call(recipient[key1]);
const isobject = type === "[object Object]" || type === "[object Array]";
// do not write over falsey, non-undefined values if overwrite is false
if (!overwrite && !isobject && typeof recipient[key1] !== "undefined") {
return;
}
if ((overwrite && !isobject) || (!overwrite && recipient[key1] == null)) {
recipient[key1] = typeof key2 === "number" && !opts.object ? [] : {};
}
recipient = recipient[key1];
if (split.length > 0) {
key1 = getkey(split.shift());
key2 = getkey(split[0]);
}
}
// unflatten again for 'messy objects'
recipient[key1] = unflatten(target[key], opts);
});
return result;
}
function filterFlatten(flattenSrc, type) {
const result = Object.keys(flattenSrc)
.filter(key => {
const keys = key.split(".");
return keys.includes(type);
})
.reduce((object, key) => {
object[key] = flattenSrc[key];
return object;
}, {});
return result;
}
function deleteFlatten(currentSrc, deletedSrc) {
const deletedKeys = Object.keys(deletedSrc);
const result = Object.keys(currentSrc).reduce((object, key) => {
!deletedKeys.includes(key) ? (object[key] = currentSrc[key]) : null;
return object;
}, {});
return result;
}
function mergeFlatten(currentSrc, nextSrc) {
return {
...currentSrc,
...nextSrc,
};
}
export { flatten, unflatten, filterFlatten, deleteFlatten, mergeFlatten };