feelin 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +10 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/feelin.gemspec +22 -0
- data/lib/feelin/js/node_modules/.package-lock.json +67 -0
- data/lib/feelin/js/node_modules/@lezer/common/LICENSE +21 -0
- data/lib/feelin/js/node_modules/@lezer/common/README.md +14 -0
- data/lib/feelin/js/node_modules/@lezer/common/dist/index.cjs +2181 -0
- data/lib/feelin/js/node_modules/@lezer/common/dist/index.d.cts +1137 -0
- data/lib/feelin/js/node_modules/@lezer/common/dist/index.d.ts +1137 -0
- data/lib/feelin/js/node_modules/@lezer/common/dist/index.js +2168 -0
- data/lib/feelin/js/node_modules/@lezer/common/package.json +32 -0
- data/lib/feelin/js/node_modules/@lezer/highlight/LICENSE +21 -0
- data/lib/feelin/js/node_modules/@lezer/highlight/README.md +14 -0
- data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.cjs +915 -0
- data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.d.cts +621 -0
- data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.d.ts +623 -0
- data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.js +904 -0
- data/lib/feelin/js/node_modules/@lezer/highlight/package.json +31 -0
- data/lib/feelin/js/node_modules/@lezer/lr/LICENSE +21 -0
- data/lib/feelin/js/node_modules/@lezer/lr/README.md +25 -0
- data/lib/feelin/js/node_modules/@lezer/lr/dist/constants.d.ts +45 -0
- data/lib/feelin/js/node_modules/@lezer/lr/dist/constants.js +5 -0
- data/lib/feelin/js/node_modules/@lezer/lr/dist/index.cjs +1890 -0
- data/lib/feelin/js/node_modules/@lezer/lr/dist/index.d.cts +303 -0
- data/lib/feelin/js/node_modules/@lezer/lr/dist/index.d.ts +303 -0
- data/lib/feelin/js/node_modules/@lezer/lr/dist/index.js +1883 -0
- data/lib/feelin/js/node_modules/@lezer/lr/package.json +32 -0
- data/lib/feelin/js/node_modules/feelin/LICENSE +21 -0
- data/lib/feelin/js/node_modules/feelin/README.md +65 -0
- data/lib/feelin/js/node_modules/feelin/dist/builtins.d.ts +355 -0
- data/lib/feelin/js/node_modules/feelin/dist/index.cjs +2072 -0
- data/lib/feelin/js/node_modules/feelin/dist/index.cjs.map +1 -0
- data/lib/feelin/js/node_modules/feelin/dist/index.d.ts +3 -0
- data/lib/feelin/js/node_modules/feelin/dist/index.esm.js +2063 -0
- data/lib/feelin/js/node_modules/feelin/dist/index.esm.js.map +1 -0
- data/lib/feelin/js/node_modules/feelin/dist/interpreter.d.ts +26 -0
- data/lib/feelin/js/node_modules/feelin/dist/parser.d.ts +4 -0
- data/lib/feelin/js/node_modules/feelin/dist/temporal.d.ts +6 -0
- data/lib/feelin/js/node_modules/feelin/dist/types.d.ts +35 -0
- data/lib/feelin/js/node_modules/feelin/dist/utils.d.ts +12 -0
- data/lib/feelin/js/node_modules/feelin/package.json +63 -0
- data/lib/feelin/js/node_modules/lezer-feel/LICENSE +21 -0
- data/lib/feelin/js/node_modules/lezer-feel/README.md +94 -0
- data/lib/feelin/js/node_modules/lezer-feel/dist/index.cjs +1328 -0
- data/lib/feelin/js/node_modules/lezer-feel/dist/index.cjs.map +1 -0
- data/lib/feelin/js/node_modules/lezer-feel/dist/index.d.ts +32 -0
- data/lib/feelin/js/node_modules/lezer-feel/dist/index.js +1323 -0
- data/lib/feelin/js/node_modules/lezer-feel/dist/index.js.map +1 -0
- data/lib/feelin/js/node_modules/lezer-feel/package.json +61 -0
- data/lib/feelin/js/node_modules/luxon/LICENSE.md +7 -0
- data/lib/feelin/js/node_modules/luxon/README.md +55 -0
- data/lib/feelin/js/node_modules/luxon/build/amd/luxon.js +8623 -0
- data/lib/feelin/js/node_modules/luxon/build/amd/luxon.js.map +1 -0
- data/lib/feelin/js/node_modules/luxon/build/cjs-browser/luxon.js +8621 -0
- data/lib/feelin/js/node_modules/luxon/build/cjs-browser/luxon.js.map +1 -0
- data/lib/feelin/js/node_modules/luxon/build/es6/luxon.js +8011 -0
- data/lib/feelin/js/node_modules/luxon/build/es6/luxon.js.map +1 -0
- data/lib/feelin/js/node_modules/luxon/build/global/luxon.js +8626 -0
- data/lib/feelin/js/node_modules/luxon/build/global/luxon.js.map +1 -0
- data/lib/feelin/js/node_modules/luxon/build/global/luxon.min.js +1 -0
- data/lib/feelin/js/node_modules/luxon/build/global/luxon.min.js.map +1 -0
- data/lib/feelin/js/node_modules/luxon/build/node/luxon.js +7679 -0
- data/lib/feelin/js/node_modules/luxon/build/node/luxon.js.map +1 -0
- data/lib/feelin/js/node_modules/luxon/package.json +87 -0
- data/lib/feelin/js/node_modules/luxon/src/datetime.js +2566 -0
- data/lib/feelin/js/node_modules/luxon/src/duration.js +990 -0
- data/lib/feelin/js/node_modules/luxon/src/errors.js +61 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/conversions.js +206 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/diff.js +95 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/digits.js +90 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/english.js +233 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/formats.js +176 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/formatter.js +409 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/invalid.js +14 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/locale.js +554 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/regexParser.js +335 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/tokenParser.js +505 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/util.js +316 -0
- data/lib/feelin/js/node_modules/luxon/src/impl/zoneUtil.js +34 -0
- data/lib/feelin/js/node_modules/luxon/src/info.js +205 -0
- data/lib/feelin/js/node_modules/luxon/src/interval.js +665 -0
- data/lib/feelin/js/node_modules/luxon/src/luxon.js +26 -0
- data/lib/feelin/js/node_modules/luxon/src/package.json +4 -0
- data/lib/feelin/js/node_modules/luxon/src/settings.js +180 -0
- data/lib/feelin/js/node_modules/luxon/src/zone.js +97 -0
- data/lib/feelin/js/node_modules/luxon/src/zones/IANAZone.js +231 -0
- data/lib/feelin/js/node_modules/luxon/src/zones/fixedOffsetZone.js +150 -0
- data/lib/feelin/js/node_modules/luxon/src/zones/invalidZone.js +53 -0
- data/lib/feelin/js/node_modules/luxon/src/zones/systemZone.js +61 -0
- data/lib/feelin/js/node_modules/min-dash/LICENSE +21 -0
- data/lib/feelin/js/node_modules/min-dash/README.md +38 -0
- data/lib/feelin/js/node_modules/min-dash/dist/array.d.ts +12 -0
- data/lib/feelin/js/node_modules/min-dash/dist/collection.d.ts +174 -0
- data/lib/feelin/js/node_modules/min-dash/dist/fn.d.ts +37 -0
- data/lib/feelin/js/node_modules/min-dash/dist/index.cjs +910 -0
- data/lib/feelin/js/node_modules/min-dash/dist/index.d.ts +5 -0
- data/lib/feelin/js/node_modules/min-dash/dist/index.esm.js +872 -0
- data/lib/feelin/js/node_modules/min-dash/dist/lang.d.ts +29 -0
- data/lib/feelin/js/node_modules/min-dash/dist/min-dash.js +916 -0
- data/lib/feelin/js/node_modules/min-dash/dist/min-dash.min.js +1 -0
- data/lib/feelin/js/node_modules/min-dash/dist/object.d.ts +112 -0
- data/lib/feelin/js/node_modules/min-dash/package.json +72 -0
- data/lib/feelin/js/package-lock.json +72 -0
- data/lib/feelin/js/package.json +5 -0
- data/lib/feelin/version.rb +3 -0
- data/lib/feelin.rb +63 -0
- data/spec/feelin/feelin_spec.rb +38 -0
- data/spec/spec_helper.rb +2 -0
- metadata +198 -0
@@ -0,0 +1,910 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Flatten array, one level deep.
|
5
|
+
*
|
6
|
+
* @template T
|
7
|
+
*
|
8
|
+
* @param {T[][] | T[] | null} [arr]
|
9
|
+
*
|
10
|
+
* @return {T[]}
|
11
|
+
*/
|
12
|
+
function flatten(arr) {
|
13
|
+
return Array.prototype.concat.apply([], arr);
|
14
|
+
}
|
15
|
+
|
16
|
+
const nativeToString = Object.prototype.toString;
|
17
|
+
const nativeHasOwnProperty = Object.prototype.hasOwnProperty;
|
18
|
+
|
19
|
+
function isUndefined(obj) {
|
20
|
+
return obj === undefined;
|
21
|
+
}
|
22
|
+
|
23
|
+
function isDefined(obj) {
|
24
|
+
return obj !== undefined;
|
25
|
+
}
|
26
|
+
|
27
|
+
function isNil(obj) {
|
28
|
+
return obj == null;
|
29
|
+
}
|
30
|
+
|
31
|
+
function isArray(obj) {
|
32
|
+
return nativeToString.call(obj) === '[object Array]';
|
33
|
+
}
|
34
|
+
|
35
|
+
function isObject(obj) {
|
36
|
+
return nativeToString.call(obj) === '[object Object]';
|
37
|
+
}
|
38
|
+
|
39
|
+
function isNumber(obj) {
|
40
|
+
return nativeToString.call(obj) === '[object Number]';
|
41
|
+
}
|
42
|
+
|
43
|
+
/**
|
44
|
+
* @param {any} obj
|
45
|
+
*
|
46
|
+
* @return {boolean}
|
47
|
+
*/
|
48
|
+
function isFunction(obj) {
|
49
|
+
const tag = nativeToString.call(obj);
|
50
|
+
|
51
|
+
return (
|
52
|
+
tag === '[object Function]' ||
|
53
|
+
tag === '[object AsyncFunction]' ||
|
54
|
+
tag === '[object GeneratorFunction]' ||
|
55
|
+
tag === '[object AsyncGeneratorFunction]' ||
|
56
|
+
tag === '[object Proxy]'
|
57
|
+
);
|
58
|
+
}
|
59
|
+
|
60
|
+
function isString(obj) {
|
61
|
+
return nativeToString.call(obj) === '[object String]';
|
62
|
+
}
|
63
|
+
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Ensure collection is an array.
|
67
|
+
*
|
68
|
+
* @param {Object} obj
|
69
|
+
*/
|
70
|
+
function ensureArray(obj) {
|
71
|
+
|
72
|
+
if (isArray(obj)) {
|
73
|
+
return;
|
74
|
+
}
|
75
|
+
|
76
|
+
throw new Error('must supply array');
|
77
|
+
}
|
78
|
+
|
79
|
+
/**
|
80
|
+
* Return true, if target owns a property with the given key.
|
81
|
+
*
|
82
|
+
* @param {Object} target
|
83
|
+
* @param {String} key
|
84
|
+
*
|
85
|
+
* @return {Boolean}
|
86
|
+
*/
|
87
|
+
function has(target, key) {
|
88
|
+
return !isNil(target) && nativeHasOwnProperty.call(target, key);
|
89
|
+
}
|
90
|
+
|
91
|
+
/**
|
92
|
+
* @template T
|
93
|
+
* @typedef { (
|
94
|
+
* ((e: T) => boolean) |
|
95
|
+
* ((e: T, idx: number) => boolean) |
|
96
|
+
* ((e: T, key: string) => boolean) |
|
97
|
+
* string |
|
98
|
+
* number
|
99
|
+
* ) } Matcher
|
100
|
+
*/
|
101
|
+
|
102
|
+
/**
|
103
|
+
* @template T
|
104
|
+
* @template U
|
105
|
+
*
|
106
|
+
* @typedef { (
|
107
|
+
* ((e: T) => U) | string | number
|
108
|
+
* ) } Extractor
|
109
|
+
*/
|
110
|
+
|
111
|
+
|
112
|
+
/**
|
113
|
+
* @template T
|
114
|
+
* @typedef { (val: T, key: any) => boolean } MatchFn
|
115
|
+
*/
|
116
|
+
|
117
|
+
/**
|
118
|
+
* @template T
|
119
|
+
* @typedef { T[] } ArrayCollection
|
120
|
+
*/
|
121
|
+
|
122
|
+
/**
|
123
|
+
* @template T
|
124
|
+
* @typedef { { [key: string]: T } } StringKeyValueCollection
|
125
|
+
*/
|
126
|
+
|
127
|
+
/**
|
128
|
+
* @template T
|
129
|
+
* @typedef { { [key: number]: T } } NumberKeyValueCollection
|
130
|
+
*/
|
131
|
+
|
132
|
+
/**
|
133
|
+
* @template T
|
134
|
+
* @typedef { StringKeyValueCollection<T> | NumberKeyValueCollection<T> } KeyValueCollection
|
135
|
+
*/
|
136
|
+
|
137
|
+
/**
|
138
|
+
* @template T
|
139
|
+
* @typedef { KeyValueCollection<T> | ArrayCollection<T> } Collection
|
140
|
+
*/
|
141
|
+
|
142
|
+
/**
|
143
|
+
* Find element in collection.
|
144
|
+
*
|
145
|
+
* @template T
|
146
|
+
* @param {Collection<T>} collection
|
147
|
+
* @param {Matcher<T>} matcher
|
148
|
+
*
|
149
|
+
* @return {Object}
|
150
|
+
*/
|
151
|
+
function find(collection, matcher) {
|
152
|
+
|
153
|
+
const matchFn = toMatcher(matcher);
|
154
|
+
|
155
|
+
let match;
|
156
|
+
|
157
|
+
forEach(collection, function(val, key) {
|
158
|
+
if (matchFn(val, key)) {
|
159
|
+
match = val;
|
160
|
+
|
161
|
+
return false;
|
162
|
+
}
|
163
|
+
});
|
164
|
+
|
165
|
+
return match;
|
166
|
+
|
167
|
+
}
|
168
|
+
|
169
|
+
|
170
|
+
/**
|
171
|
+
* Find element index in collection.
|
172
|
+
*
|
173
|
+
* @template T
|
174
|
+
* @param {Collection<T>} collection
|
175
|
+
* @param {Matcher<T>} matcher
|
176
|
+
*
|
177
|
+
* @return {number | string | undefined}
|
178
|
+
*/
|
179
|
+
function findIndex(collection, matcher) {
|
180
|
+
|
181
|
+
const matchFn = toMatcher(matcher);
|
182
|
+
|
183
|
+
let idx = isArray(collection) ? -1 : undefined;
|
184
|
+
|
185
|
+
forEach(collection, function(val, key) {
|
186
|
+
if (matchFn(val, key)) {
|
187
|
+
idx = key;
|
188
|
+
|
189
|
+
return false;
|
190
|
+
}
|
191
|
+
});
|
192
|
+
|
193
|
+
return idx;
|
194
|
+
}
|
195
|
+
|
196
|
+
|
197
|
+
/**
|
198
|
+
* Filter elements in collection.
|
199
|
+
*
|
200
|
+
* @template T
|
201
|
+
* @param {Collection<T>} collection
|
202
|
+
* @param {Matcher<T>} matcher
|
203
|
+
*
|
204
|
+
* @return {T[]} result
|
205
|
+
*/
|
206
|
+
function filter(collection, matcher) {
|
207
|
+
|
208
|
+
const matchFn = toMatcher(matcher);
|
209
|
+
|
210
|
+
let result = [];
|
211
|
+
|
212
|
+
forEach(collection, function(val, key) {
|
213
|
+
if (matchFn(val, key)) {
|
214
|
+
result.push(val);
|
215
|
+
}
|
216
|
+
});
|
217
|
+
|
218
|
+
return result;
|
219
|
+
}
|
220
|
+
|
221
|
+
|
222
|
+
/**
|
223
|
+
* Iterate over collection; returning something
|
224
|
+
* (non-undefined) will stop iteration.
|
225
|
+
*
|
226
|
+
* @template T
|
227
|
+
* @param {Collection<T>} collection
|
228
|
+
* @param { ((item: T, idx: number) => (boolean|void)) | ((item: T, key: string) => (boolean|void)) } iterator
|
229
|
+
*
|
230
|
+
* @return {T} return result that stopped the iteration
|
231
|
+
*/
|
232
|
+
function forEach(collection, iterator) {
|
233
|
+
|
234
|
+
let val,
|
235
|
+
result;
|
236
|
+
|
237
|
+
if (isUndefined(collection)) {
|
238
|
+
return;
|
239
|
+
}
|
240
|
+
|
241
|
+
const convertKey = isArray(collection) ? toNum : identity;
|
242
|
+
|
243
|
+
for (let key in collection) {
|
244
|
+
|
245
|
+
if (has(collection, key)) {
|
246
|
+
val = collection[key];
|
247
|
+
|
248
|
+
result = iterator(val, convertKey(key));
|
249
|
+
|
250
|
+
if (result === false) {
|
251
|
+
return val;
|
252
|
+
}
|
253
|
+
}
|
254
|
+
}
|
255
|
+
}
|
256
|
+
|
257
|
+
/**
|
258
|
+
* Return collection without element.
|
259
|
+
*
|
260
|
+
* @template T
|
261
|
+
* @param {ArrayCollection<T>} arr
|
262
|
+
* @param {Matcher<T>} matcher
|
263
|
+
*
|
264
|
+
* @return {T[]}
|
265
|
+
*/
|
266
|
+
function without(arr, matcher) {
|
267
|
+
|
268
|
+
if (isUndefined(arr)) {
|
269
|
+
return [];
|
270
|
+
}
|
271
|
+
|
272
|
+
ensureArray(arr);
|
273
|
+
|
274
|
+
const matchFn = toMatcher(matcher);
|
275
|
+
|
276
|
+
return arr.filter(function(el, idx) {
|
277
|
+
return !matchFn(el, idx);
|
278
|
+
});
|
279
|
+
|
280
|
+
}
|
281
|
+
|
282
|
+
|
283
|
+
/**
|
284
|
+
* Reduce collection, returning a single result.
|
285
|
+
*
|
286
|
+
* @template T
|
287
|
+
* @template V
|
288
|
+
*
|
289
|
+
* @param {Collection<T>} collection
|
290
|
+
* @param {(result: V, entry: T, index: any) => V} iterator
|
291
|
+
* @param {V} result
|
292
|
+
*
|
293
|
+
* @return {V} result returned from last iterator
|
294
|
+
*/
|
295
|
+
function reduce(collection, iterator, result) {
|
296
|
+
|
297
|
+
forEach(collection, function(value, idx) {
|
298
|
+
result = iterator(result, value, idx);
|
299
|
+
});
|
300
|
+
|
301
|
+
return result;
|
302
|
+
}
|
303
|
+
|
304
|
+
|
305
|
+
/**
|
306
|
+
* Return true if every element in the collection
|
307
|
+
* matches the criteria.
|
308
|
+
*
|
309
|
+
* @param {Object|Array} collection
|
310
|
+
* @param {Function} matcher
|
311
|
+
*
|
312
|
+
* @return {Boolean}
|
313
|
+
*/
|
314
|
+
function every(collection, matcher) {
|
315
|
+
|
316
|
+
return !!reduce(collection, function(matches, val, key) {
|
317
|
+
return matches && matcher(val, key);
|
318
|
+
}, true);
|
319
|
+
}
|
320
|
+
|
321
|
+
|
322
|
+
/**
|
323
|
+
* Return true if some elements in the collection
|
324
|
+
* match the criteria.
|
325
|
+
*
|
326
|
+
* @param {Object|Array} collection
|
327
|
+
* @param {Function} matcher
|
328
|
+
*
|
329
|
+
* @return {Boolean}
|
330
|
+
*/
|
331
|
+
function some(collection, matcher) {
|
332
|
+
|
333
|
+
return !!find(collection, matcher);
|
334
|
+
}
|
335
|
+
|
336
|
+
|
337
|
+
/**
|
338
|
+
* Transform a collection into another collection
|
339
|
+
* by piping each member through the given fn.
|
340
|
+
*
|
341
|
+
* @param {Object|Array} collection
|
342
|
+
* @param {Function} fn
|
343
|
+
*
|
344
|
+
* @return {Array} transformed collection
|
345
|
+
*/
|
346
|
+
function map(collection, fn) {
|
347
|
+
|
348
|
+
let result = [];
|
349
|
+
|
350
|
+
forEach(collection, function(val, key) {
|
351
|
+
result.push(fn(val, key));
|
352
|
+
});
|
353
|
+
|
354
|
+
return result;
|
355
|
+
}
|
356
|
+
|
357
|
+
|
358
|
+
/**
|
359
|
+
* Get the collections keys.
|
360
|
+
*
|
361
|
+
* @param {Object|Array} collection
|
362
|
+
*
|
363
|
+
* @return {Array}
|
364
|
+
*/
|
365
|
+
function keys(collection) {
|
366
|
+
return collection && Object.keys(collection) || [];
|
367
|
+
}
|
368
|
+
|
369
|
+
|
370
|
+
/**
|
371
|
+
* Shorthand for `keys(o).length`.
|
372
|
+
*
|
373
|
+
* @param {Object|Array} collection
|
374
|
+
*
|
375
|
+
* @return {Number}
|
376
|
+
*/
|
377
|
+
function size(collection) {
|
378
|
+
return keys(collection).length;
|
379
|
+
}
|
380
|
+
|
381
|
+
|
382
|
+
/**
|
383
|
+
* Get the values in the collection.
|
384
|
+
*
|
385
|
+
* @param {Object|Array} collection
|
386
|
+
*
|
387
|
+
* @return {Array}
|
388
|
+
*/
|
389
|
+
function values(collection) {
|
390
|
+
return map(collection, (val) => val);
|
391
|
+
}
|
392
|
+
|
393
|
+
|
394
|
+
/**
|
395
|
+
* Group collection members by attribute.
|
396
|
+
*
|
397
|
+
* @param {Object|Array} collection
|
398
|
+
* @param {Extractor} extractor
|
399
|
+
*
|
400
|
+
* @return {Object} map with { attrValue => [ a, b, c ] }
|
401
|
+
*/
|
402
|
+
function groupBy(collection, extractor, grouped = {}) {
|
403
|
+
|
404
|
+
extractor = toExtractor(extractor);
|
405
|
+
|
406
|
+
forEach(collection, function(val) {
|
407
|
+
let discriminator = extractor(val) || '_';
|
408
|
+
|
409
|
+
let group = grouped[discriminator];
|
410
|
+
|
411
|
+
if (!group) {
|
412
|
+
group = grouped[discriminator] = [];
|
413
|
+
}
|
414
|
+
|
415
|
+
group.push(val);
|
416
|
+
});
|
417
|
+
|
418
|
+
return grouped;
|
419
|
+
}
|
420
|
+
|
421
|
+
|
422
|
+
function uniqueBy(extractor, ...collections) {
|
423
|
+
|
424
|
+
extractor = toExtractor(extractor);
|
425
|
+
|
426
|
+
let grouped = {};
|
427
|
+
|
428
|
+
forEach(collections, (c) => groupBy(c, extractor, grouped));
|
429
|
+
|
430
|
+
let result = map(grouped, function(val, key) {
|
431
|
+
return val[0];
|
432
|
+
});
|
433
|
+
|
434
|
+
return result;
|
435
|
+
}
|
436
|
+
|
437
|
+
|
438
|
+
const unionBy = uniqueBy;
|
439
|
+
|
440
|
+
|
441
|
+
|
442
|
+
/**
|
443
|
+
* Sort collection by criteria.
|
444
|
+
*
|
445
|
+
* @template T
|
446
|
+
*
|
447
|
+
* @param {Collection<T>} collection
|
448
|
+
* @param {Extractor<T, number | string>} extractor
|
449
|
+
*
|
450
|
+
* @return {Array}
|
451
|
+
*/
|
452
|
+
function sortBy(collection, extractor) {
|
453
|
+
|
454
|
+
extractor = toExtractor(extractor);
|
455
|
+
|
456
|
+
let sorted = [];
|
457
|
+
|
458
|
+
forEach(collection, function(value, key) {
|
459
|
+
let disc = extractor(value, key);
|
460
|
+
|
461
|
+
let entry = {
|
462
|
+
d: disc,
|
463
|
+
v: value
|
464
|
+
};
|
465
|
+
|
466
|
+
for (var idx = 0; idx < sorted.length; idx++) {
|
467
|
+
let { d } = sorted[idx];
|
468
|
+
|
469
|
+
if (disc < d) {
|
470
|
+
sorted.splice(idx, 0, entry);
|
471
|
+
return;
|
472
|
+
}
|
473
|
+
}
|
474
|
+
|
475
|
+
// not inserted, append (!)
|
476
|
+
sorted.push(entry);
|
477
|
+
});
|
478
|
+
|
479
|
+
return map(sorted, (e) => e.v);
|
480
|
+
}
|
481
|
+
|
482
|
+
|
483
|
+
/**
|
484
|
+
* Create an object pattern matcher.
|
485
|
+
*
|
486
|
+
* @example
|
487
|
+
*
|
488
|
+
* ```javascript
|
489
|
+
* const matcher = matchPattern({ id: 1 });
|
490
|
+
*
|
491
|
+
* let element = find(elements, matcher);
|
492
|
+
* ```
|
493
|
+
*
|
494
|
+
* @template T
|
495
|
+
*
|
496
|
+
* @param {T} pattern
|
497
|
+
*
|
498
|
+
* @return { (el: any) => boolean } matcherFn
|
499
|
+
*/
|
500
|
+
function matchPattern(pattern) {
|
501
|
+
|
502
|
+
return function(el) {
|
503
|
+
|
504
|
+
return every(pattern, function(val, key) {
|
505
|
+
return el[key] === val;
|
506
|
+
});
|
507
|
+
|
508
|
+
};
|
509
|
+
}
|
510
|
+
|
511
|
+
|
512
|
+
/**
|
513
|
+
* @param {string | ((e: any) => any) } extractor
|
514
|
+
*
|
515
|
+
* @return { (e: any) => any }
|
516
|
+
*/
|
517
|
+
function toExtractor(extractor) {
|
518
|
+
|
519
|
+
/**
|
520
|
+
* @satisfies { (e: any) => any }
|
521
|
+
*/
|
522
|
+
return isFunction(extractor) ? extractor : (e) => {
|
523
|
+
|
524
|
+
// @ts-ignore: just works
|
525
|
+
return e[extractor];
|
526
|
+
};
|
527
|
+
}
|
528
|
+
|
529
|
+
|
530
|
+
/**
|
531
|
+
* @template T
|
532
|
+
* @param {Matcher<T>} matcher
|
533
|
+
*
|
534
|
+
* @return {MatchFn<T>}
|
535
|
+
*/
|
536
|
+
function toMatcher(matcher) {
|
537
|
+
return isFunction(matcher) ? matcher : (e) => {
|
538
|
+
return e === matcher;
|
539
|
+
};
|
540
|
+
}
|
541
|
+
|
542
|
+
|
543
|
+
function identity(arg) {
|
544
|
+
return arg;
|
545
|
+
}
|
546
|
+
|
547
|
+
function toNum(arg) {
|
548
|
+
return Number(arg);
|
549
|
+
}
|
550
|
+
|
551
|
+
/* global setTimeout clearTimeout */
|
552
|
+
|
553
|
+
/**
|
554
|
+
* @typedef { {
|
555
|
+
* (...args: any[]): any;
|
556
|
+
* flush: () => void;
|
557
|
+
* cancel: () => void;
|
558
|
+
* } } DebouncedFunction
|
559
|
+
*/
|
560
|
+
|
561
|
+
/**
|
562
|
+
* Debounce fn, calling it only once if the given time
|
563
|
+
* elapsed between calls.
|
564
|
+
*
|
565
|
+
* Lodash-style the function exposes methods to `#clear`
|
566
|
+
* and `#flush` to control internal behavior.
|
567
|
+
*
|
568
|
+
* @param {Function} fn
|
569
|
+
* @param {Number} timeout
|
570
|
+
*
|
571
|
+
* @return {DebouncedFunction} debounced function
|
572
|
+
*/
|
573
|
+
function debounce(fn, timeout) {
|
574
|
+
|
575
|
+
let timer;
|
576
|
+
|
577
|
+
let lastArgs;
|
578
|
+
let lastThis;
|
579
|
+
|
580
|
+
let lastNow;
|
581
|
+
|
582
|
+
function fire(force) {
|
583
|
+
|
584
|
+
let now = Date.now();
|
585
|
+
|
586
|
+
let scheduledDiff = force ? 0 : (lastNow + timeout) - now;
|
587
|
+
|
588
|
+
if (scheduledDiff > 0) {
|
589
|
+
return schedule(scheduledDiff);
|
590
|
+
}
|
591
|
+
|
592
|
+
fn.apply(lastThis, lastArgs);
|
593
|
+
|
594
|
+
clear();
|
595
|
+
}
|
596
|
+
|
597
|
+
function schedule(timeout) {
|
598
|
+
timer = setTimeout(fire, timeout);
|
599
|
+
}
|
600
|
+
|
601
|
+
function clear() {
|
602
|
+
if (timer) {
|
603
|
+
clearTimeout(timer);
|
604
|
+
}
|
605
|
+
|
606
|
+
timer = lastNow = lastArgs = lastThis = undefined;
|
607
|
+
}
|
608
|
+
|
609
|
+
function flush() {
|
610
|
+
if (timer) {
|
611
|
+
fire(true);
|
612
|
+
}
|
613
|
+
|
614
|
+
clear();
|
615
|
+
}
|
616
|
+
|
617
|
+
/**
|
618
|
+
* @type { DebouncedFunction }
|
619
|
+
*/
|
620
|
+
function callback(...args) {
|
621
|
+
lastNow = Date.now();
|
622
|
+
|
623
|
+
lastArgs = args;
|
624
|
+
lastThis = this;
|
625
|
+
|
626
|
+
// ensure an execution is scheduled
|
627
|
+
if (!timer) {
|
628
|
+
schedule(timeout);
|
629
|
+
}
|
630
|
+
}
|
631
|
+
|
632
|
+
callback.flush = flush;
|
633
|
+
callback.cancel = clear;
|
634
|
+
|
635
|
+
return callback;
|
636
|
+
}
|
637
|
+
|
638
|
+
/**
|
639
|
+
* Throttle fn, calling at most once
|
640
|
+
* in the given interval.
|
641
|
+
*
|
642
|
+
* @param {Function} fn
|
643
|
+
* @param {Number} interval
|
644
|
+
*
|
645
|
+
* @return {Function} throttled function
|
646
|
+
*/
|
647
|
+
function throttle(fn, interval) {
|
648
|
+
let throttling = false;
|
649
|
+
|
650
|
+
return function(...args) {
|
651
|
+
|
652
|
+
if (throttling) {
|
653
|
+
return;
|
654
|
+
}
|
655
|
+
|
656
|
+
fn(...args);
|
657
|
+
throttling = true;
|
658
|
+
|
659
|
+
setTimeout(() => {
|
660
|
+
throttling = false;
|
661
|
+
}, interval);
|
662
|
+
};
|
663
|
+
}
|
664
|
+
|
665
|
+
/**
|
666
|
+
* Bind function against target <this>.
|
667
|
+
*
|
668
|
+
* @param {Function} fn
|
669
|
+
* @param {Object} target
|
670
|
+
*
|
671
|
+
* @return {Function} bound function
|
672
|
+
*/
|
673
|
+
function bind(fn, target) {
|
674
|
+
return fn.bind(target);
|
675
|
+
}
|
676
|
+
|
677
|
+
/**
|
678
|
+
* Convenience wrapper for `Object.assign`.
|
679
|
+
*
|
680
|
+
* @param {Object} target
|
681
|
+
* @param {...Object} others
|
682
|
+
*
|
683
|
+
* @return {Object} the target
|
684
|
+
*/
|
685
|
+
function assign(target, ...others) {
|
686
|
+
return Object.assign(target, ...others);
|
687
|
+
}
|
688
|
+
|
689
|
+
/**
|
690
|
+
* Sets a nested property of a given object to the specified value.
|
691
|
+
*
|
692
|
+
* This mutates the object and returns it.
|
693
|
+
*
|
694
|
+
* @template T
|
695
|
+
*
|
696
|
+
* @param {T} target The target of the set operation.
|
697
|
+
* @param {(string|number)[]} path The path to the nested value.
|
698
|
+
* @param {any} value The value to set.
|
699
|
+
*
|
700
|
+
* @return {T}
|
701
|
+
*/
|
702
|
+
function set(target, path, value) {
|
703
|
+
|
704
|
+
let currentTarget = target;
|
705
|
+
|
706
|
+
forEach(path, function(key, idx) {
|
707
|
+
|
708
|
+
if (typeof key !== 'number' && typeof key !== 'string') {
|
709
|
+
throw new Error('illegal key type: ' + typeof key + '. Key should be of type number or string.');
|
710
|
+
}
|
711
|
+
|
712
|
+
if (key === 'constructor') {
|
713
|
+
throw new Error('illegal key: constructor');
|
714
|
+
}
|
715
|
+
|
716
|
+
if (key === '__proto__') {
|
717
|
+
throw new Error('illegal key: __proto__');
|
718
|
+
}
|
719
|
+
|
720
|
+
let nextKey = path[idx + 1];
|
721
|
+
let nextTarget = currentTarget[key];
|
722
|
+
|
723
|
+
if (isDefined(nextKey) && isNil(nextTarget)) {
|
724
|
+
nextTarget = currentTarget[key] = isNaN(+nextKey) ? {} : [];
|
725
|
+
}
|
726
|
+
|
727
|
+
if (isUndefined(nextKey)) {
|
728
|
+
if (isUndefined(value)) {
|
729
|
+
delete currentTarget[key];
|
730
|
+
} else {
|
731
|
+
currentTarget[key] = value;
|
732
|
+
}
|
733
|
+
} else {
|
734
|
+
currentTarget = nextTarget;
|
735
|
+
}
|
736
|
+
});
|
737
|
+
|
738
|
+
return target;
|
739
|
+
}
|
740
|
+
|
741
|
+
|
742
|
+
/**
|
743
|
+
* Gets a nested property of a given object.
|
744
|
+
*
|
745
|
+
* @param {Object} target The target of the get operation.
|
746
|
+
* @param {(string|number)[]} path The path to the nested value.
|
747
|
+
* @param {any} [defaultValue] The value to return if no value exists.
|
748
|
+
*
|
749
|
+
* @return {any}
|
750
|
+
*/
|
751
|
+
function get(target, path, defaultValue) {
|
752
|
+
|
753
|
+
let currentTarget = target;
|
754
|
+
|
755
|
+
forEach(path, function(key) {
|
756
|
+
|
757
|
+
// accessing nil property yields <undefined>
|
758
|
+
if (isNil(currentTarget)) {
|
759
|
+
currentTarget = undefined;
|
760
|
+
|
761
|
+
return false;
|
762
|
+
}
|
763
|
+
|
764
|
+
currentTarget = currentTarget[key];
|
765
|
+
});
|
766
|
+
|
767
|
+
return isUndefined(currentTarget) ? defaultValue : currentTarget;
|
768
|
+
}
|
769
|
+
|
770
|
+
/**
|
771
|
+
* Pick properties from the given target.
|
772
|
+
*
|
773
|
+
* @template T
|
774
|
+
* @template {any[]} V
|
775
|
+
*
|
776
|
+
* @param {T} target
|
777
|
+
* @param {V} properties
|
778
|
+
*
|
779
|
+
* @return Pick<T, V>
|
780
|
+
*/
|
781
|
+
function pick(target, properties) {
|
782
|
+
|
783
|
+
let result = {};
|
784
|
+
|
785
|
+
let obj = Object(target);
|
786
|
+
|
787
|
+
forEach(properties, function(prop) {
|
788
|
+
|
789
|
+
if (prop in obj) {
|
790
|
+
result[prop] = target[prop];
|
791
|
+
}
|
792
|
+
});
|
793
|
+
|
794
|
+
return result;
|
795
|
+
}
|
796
|
+
|
797
|
+
/**
|
798
|
+
* Pick all target properties, excluding the given ones.
|
799
|
+
*
|
800
|
+
* @template T
|
801
|
+
* @template {any[]} V
|
802
|
+
*
|
803
|
+
* @param {T} target
|
804
|
+
* @param {V} properties
|
805
|
+
*
|
806
|
+
* @return {Omit<T, V>} target
|
807
|
+
*/
|
808
|
+
function omit(target, properties) {
|
809
|
+
|
810
|
+
let result = {};
|
811
|
+
|
812
|
+
let obj = Object(target);
|
813
|
+
|
814
|
+
forEach(obj, function(prop, key) {
|
815
|
+
|
816
|
+
if (properties.indexOf(key) === -1) {
|
817
|
+
result[key] = prop;
|
818
|
+
}
|
819
|
+
});
|
820
|
+
|
821
|
+
return result;
|
822
|
+
}
|
823
|
+
|
824
|
+
/**
|
825
|
+
* Recursively merge `...sources` into given target.
|
826
|
+
*
|
827
|
+
* Does support merging objects; does not support merging arrays.
|
828
|
+
*
|
829
|
+
* @param {Object} target
|
830
|
+
* @param {...Object} sources
|
831
|
+
*
|
832
|
+
* @return {Object} the target
|
833
|
+
*/
|
834
|
+
function merge(target, ...sources) {
|
835
|
+
|
836
|
+
if (!sources.length) {
|
837
|
+
return target;
|
838
|
+
}
|
839
|
+
|
840
|
+
forEach(sources, function(source) {
|
841
|
+
|
842
|
+
// skip non-obj sources, i.e. null
|
843
|
+
if (!source || !isObject(source)) {
|
844
|
+
return;
|
845
|
+
}
|
846
|
+
|
847
|
+
forEach(source, function(sourceVal, key) {
|
848
|
+
|
849
|
+
if (key === '__proto__') {
|
850
|
+
return;
|
851
|
+
}
|
852
|
+
|
853
|
+
let targetVal = target[key];
|
854
|
+
|
855
|
+
if (isObject(sourceVal)) {
|
856
|
+
|
857
|
+
if (!isObject(targetVal)) {
|
858
|
+
|
859
|
+
// override target[key] with object
|
860
|
+
targetVal = {};
|
861
|
+
}
|
862
|
+
|
863
|
+
target[key] = merge(targetVal, sourceVal);
|
864
|
+
} else {
|
865
|
+
target[key] = sourceVal;
|
866
|
+
}
|
867
|
+
|
868
|
+
});
|
869
|
+
});
|
870
|
+
|
871
|
+
return target;
|
872
|
+
}
|
873
|
+
|
874
|
+
exports.assign = assign;
|
875
|
+
exports.bind = bind;
|
876
|
+
exports.debounce = debounce;
|
877
|
+
exports.ensureArray = ensureArray;
|
878
|
+
exports.every = every;
|
879
|
+
exports.filter = filter;
|
880
|
+
exports.find = find;
|
881
|
+
exports.findIndex = findIndex;
|
882
|
+
exports.flatten = flatten;
|
883
|
+
exports.forEach = forEach;
|
884
|
+
exports.get = get;
|
885
|
+
exports.groupBy = groupBy;
|
886
|
+
exports.has = has;
|
887
|
+
exports.isArray = isArray;
|
888
|
+
exports.isDefined = isDefined;
|
889
|
+
exports.isFunction = isFunction;
|
890
|
+
exports.isNil = isNil;
|
891
|
+
exports.isNumber = isNumber;
|
892
|
+
exports.isObject = isObject;
|
893
|
+
exports.isString = isString;
|
894
|
+
exports.isUndefined = isUndefined;
|
895
|
+
exports.keys = keys;
|
896
|
+
exports.map = map;
|
897
|
+
exports.matchPattern = matchPattern;
|
898
|
+
exports.merge = merge;
|
899
|
+
exports.omit = omit;
|
900
|
+
exports.pick = pick;
|
901
|
+
exports.reduce = reduce;
|
902
|
+
exports.set = set;
|
903
|
+
exports.size = size;
|
904
|
+
exports.some = some;
|
905
|
+
exports.sortBy = sortBy;
|
906
|
+
exports.throttle = throttle;
|
907
|
+
exports.unionBy = unionBy;
|
908
|
+
exports.uniqueBy = uniqueBy;
|
909
|
+
exports.values = values;
|
910
|
+
exports.without = without;
|