| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************************************/ | 
					
						
							| 
									
										
										
										
											2016-08-21 02:19:24 +03:00
										 |  |  | ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define) | 
					
						
							|  |  |  | (function(require){ var module={} // make module AMD/node compatible...
 | 
					
						
							| 
									
										
										
										
											2016-08-20 22:49:36 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 00:26:43 +03:00
										 |  |  | require('object-run') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-12 16:13:32 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // Object...
 | 
					
						
							| 
									
										
										
										
											2015-12-31 10:37:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-12 16:13:32 +03:00
										 |  |  | // Get all the accessible keys...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This is different to Object.keys(..) in that this will return keys
 | 
					
						
							|  |  |  | // from all the prototypes in the inheritance chain while .keys(..) will 
 | 
					
						
							|  |  |  | // only return the keys defined in the current object only.
 | 
					
						
							|  |  |  | Object.deepKeys = function(obj){ | 
					
						
							|  |  |  | 	var res = [] | 
					
						
							|  |  |  | 	while(obj != null){ | 
					
						
							|  |  |  | 		res = res.concat(Object.keys(obj)) | 
					
						
							|  |  |  | 		obj = obj.__proto__ | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-07-03 00:26:43 +03:00
										 |  |  | 	return res.unique() } | 
					
						
							| 
									
										
										
										
											2018-12-12 16:13:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Make a full key set copy of an object...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: this will not deep-copy the values...
 | 
					
						
							|  |  |  | Object.flatCopy = function(obj){ | 
					
						
							|  |  |  | 	var res = {} | 
					
						
							|  |  |  | 	Object.deepKeys(obj).forEach(function(key){ | 
					
						
							|  |  |  | 		res[key] = obj[key] | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 	return res } | 
					
						
							| 
									
										
										
										
											2018-12-12 16:13:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // Array...
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-14 15:18:06 +03:00
										 |  |  | // Array.prototype.flat polyfill...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: .flat(..) is not yet supported in IE/Edge...
 | 
					
						
							|  |  |  | Array.prototype.flat | 
					
						
							|  |  |  | 	|| (Array.prototype.flat = function(depth){ | 
					
						
							|  |  |  | 		depth = typeof(depth) == typeof(123) ? depth : 1 | 
					
						
							|  |  |  | 		return this.reduce(function(res, e){  | 
					
						
							|  |  |  | 			return res.concat(e instanceof Array && depth > 0 ?  | 
					
						
							|  |  |  | 				e.flat(depth-1)  | 
					
						
							|  |  |  | 				: [e]) }, []) }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-12 16:13:32 +03:00
										 |  |  | // Array.prototype.includes polyfill...
 | 
					
						
							| 
									
										
										
										
											2018-08-21 14:31:19 +03:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2018-12-12 16:13:32 +03:00
										 |  |  | Array.prototype.includes | 
					
						
							|  |  |  | 	|| (Array.prototype.includes = function(value){ | 
					
						
							|  |  |  | 		return this.indexOf(value) >= 0 })  | 
					
						
							| 
									
										
										
										
											2018-08-21 14:31:19 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 22:02:15 +03:00
										 |  |  | // first/last element access short-hands...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	.first()
 | 
					
						
							|  |  |  | //		-> elem
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	.first(value)
 | 
					
						
							|  |  |  | //		-> array
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | Array.prototype.first | 
					
						
							|  |  |  | 	|| (Array.prototype.first = function(value){ | 
					
						
							|  |  |  | 		return arguments.length > 0 ? | 
					
						
							|  |  |  | 			((this[0] = value), this) | 
					
						
							|  |  |  | 			: this[0]}) | 
					
						
							|  |  |  | Array.prototype.last | 
					
						
							|  |  |  | 	|| (Array.prototype.last = function(value){ | 
					
						
							|  |  |  | 		return arguments.length > 0 ? | 
					
						
							|  |  |  | 			((this[this.length - 1 || 0] = value), this) | 
					
						
							|  |  |  | 			: this[this.length - 1]}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*/ XXX not yet sure should these be funcs or props... | 
					
						
							|  |  |  | 'first' in Array.prototype | 
					
						
							|  |  |  | 	|| Object.defineProperty(Array.prototype, 'first', { | 
					
						
							|  |  |  | 		enumerable: false, | 
					
						
							|  |  |  | 		get : function () { | 
					
						
							|  |  |  | 			return this[0] }, | 
					
						
							|  |  |  | 		set : function(value){ | 
					
						
							|  |  |  | 			this[0] = value  | 
					
						
							|  |  |  | 			return this }, }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 'last' in Array.prototype | 
					
						
							|  |  |  | 	|| Object.defineProperty(Array.prototype, 'last', { | 
					
						
							|  |  |  | 		enumerable: false, | 
					
						
							|  |  |  | 		get : function () { | 
					
						
							|  |  |  | 			return this[this.length - 1] }, | 
					
						
							|  |  |  | 		set : function(value){ | 
					
						
							|  |  |  | 			this[this.length - 1 || 0] = value  | 
					
						
							|  |  |  | 			return this }, }) | 
					
						
							|  |  |  | //*/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-31 10:37:21 +03:00
										 |  |  | // Compact a sparse array...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: this will not compact in-place.
 | 
					
						
							|  |  |  | Array.prototype.compact = function(){ | 
					
						
							| 
									
										
										
										
											2018-04-03 00:07:38 +03:00
										 |  |  | 	return this.filter(function(){ return true }) } | 
					
						
							| 
									
										
										
										
											2018-03-23 00:47:39 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-14 15:18:06 +03:00
										 |  |  | // like .length but for sparse arrays will return the element count...
 | 
					
						
							| 
									
										
										
										
											2018-12-14 16:31:34 +03:00
										 |  |  | 'len' in Array.prototype | 
					
						
							|  |  |  | 	|| Object.defineProperty(Array.prototype, 'len', { | 
					
						
							|  |  |  | 		get : function () { | 
					
						
							|  |  |  | 			return Object.keys(this).length | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		set : function(val){}, | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2018-11-14 15:18:06 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-23 00:47:39 +03:00
										 |  |  | // Convert an array to object...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Format:
 | 
					
						
							|  |  |  | // 	{
 | 
					
						
							|  |  |  | // 		<item>: <index>,
 | 
					
						
							|  |  |  | // 		...
 | 
					
						
							|  |  |  | // 	}
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: items should be strings, other types will get converted to 
 | 
					
						
							|  |  |  | // 		strings and thus may mess things up.
 | 
					
						
							|  |  |  | // NOTE: this will forget repeating items...
 | 
					
						
							|  |  |  | // NOTE: normalize will slow things down...
 | 
					
						
							|  |  |  | Array.prototype.toKeys = function(normalize){ | 
					
						
							| 
									
										
										
										
											2018-03-23 02:22:42 +03:00
										 |  |  | 	return normalize ?  | 
					
						
							|  |  |  | 		this.reduce(function(r, e, i){ | 
					
						
							|  |  |  | 			r[normalize(e)] = i | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 			return r }, {}) | 
					
						
							| 
									
										
										
										
											2018-03-23 02:22:42 +03:00
										 |  |  | 		: this.reduce(function(r, e, i){ | 
					
						
							|  |  |  | 			r[e] = i | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 			return r }, {}) } | 
					
						
							| 
									
										
										
										
											2018-04-03 00:07:38 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Convert an array to a map...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This is similar to Array.prototype.toKeys(..) but does not restrict 
 | 
					
						
							|  |  |  | // value type to string.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Format:
 | 
					
						
							|  |  |  | // 	Map([
 | 
					
						
							|  |  |  | // 		[<item>, <index>],
 | 
					
						
							|  |  |  | // 		...
 | 
					
						
							|  |  |  | // 	])
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: this will forget repeating items...
 | 
					
						
							|  |  |  | // NOTE: normalize will slow things down...
 | 
					
						
							|  |  |  | Array.prototype.toMap = function(normalize){ | 
					
						
							|  |  |  | 	return normalize ?  | 
					
						
							| 
									
										
										
										
											2018-08-08 03:55:38 +03:00
										 |  |  | 		this | 
					
						
							|  |  |  | 			.reduce(function(m, e, i){ | 
					
						
							|  |  |  | 				m.set(normalize(e), i) | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 				return m }, new Map()) | 
					
						
							| 
									
										
										
										
											2018-08-08 03:55:38 +03:00
										 |  |  | 		: this | 
					
						
							|  |  |  | 			.reduce(function(m, e, i){ | 
					
						
							|  |  |  | 				m.set(e, i) | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 				return m }, new Map()) } | 
					
						
							| 
									
										
										
										
											2015-12-31 10:37:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-23 00:47:39 +03:00
										 |  |  | // Return an array with duplicate elements removed...
 | 
					
						
							| 
									
										
										
										
											2015-12-31 10:37:21 +03:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-07-14 04:31:02 +03:00
										 |  |  | // NOTE: order is preserved... 
 | 
					
						
							| 
									
										
										
										
											2016-04-14 16:37:58 +03:00
										 |  |  | Array.prototype.unique = function(normalize){ | 
					
						
							| 
									
										
										
										
											2018-08-08 03:55:38 +03:00
										 |  |  | 	return normalize ?  | 
					
						
							|  |  |  | 		[...new Map(this.map(function(e){ return [normalize(e), e] })).values()] | 
					
						
							| 
									
										
										
										
											2019-11-04 04:27:10 +03:00
										 |  |  | 		: [...new Set(this)] } | 
					
						
							|  |  |  | Array.prototype.tailUnique = function(normalize){ | 
					
						
							|  |  |  | 	return this | 
					
						
							|  |  |  | 		.slice() | 
					
						
							|  |  |  | 		.reverse() | 
					
						
							|  |  |  | 		.unique(normalize) | 
					
						
							|  |  |  | 		.reverse() } | 
					
						
							| 
									
										
										
										
											2018-03-23 00:47:39 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-31 10:37:21 +03:00
										 |  |  | // Compare two arrays...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | Array.prototype.cmp = function(other){ | 
					
						
							|  |  |  | 	if(this === other){ | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 		return true } | 
					
						
							| 
									
										
										
										
											2015-12-31 10:37:21 +03:00
										 |  |  | 	if(this.length != other.length){ | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 		return false } | 
					
						
							| 
									
										
										
										
											2015-12-31 10:37:21 +03:00
										 |  |  | 	for(var i=0; i<this.length; i++){ | 
					
						
							|  |  |  | 		if(this[i] != other[i]){ | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 			return false } } | 
					
						
							|  |  |  | 	return true } | 
					
						
							| 
									
										
										
										
											2015-12-31 10:37:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-12 16:13:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-31 10:37:21 +03:00
										 |  |  | // Compare two Arrays as sets...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This will ignore order
 | 
					
						
							| 
									
										
										
										
											2018-04-03 00:07:38 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | // XXX should we use Set(..) here???
 | 
					
						
							| 
									
										
										
										
											2015-12-31 10:37:21 +03:00
										 |  |  | Array.prototype.setCmp = function(other){ | 
					
						
							|  |  |  | 	return this === other  | 
					
						
							| 
									
										
										
										
											2018-03-23 02:22:42 +03:00
										 |  |  | 		|| this | 
					
						
							|  |  |  | 			.unique() | 
					
						
							|  |  |  | 			.sort() | 
					
						
							|  |  |  | 			.cmp(other | 
					
						
							|  |  |  | 				.unique() | 
					
						
							|  |  |  | 				.sort()) } | 
					
						
							| 
									
										
										
										
											2015-12-31 10:37:21 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-01 19:25:58 +03:00
										 |  |  | Array.prototype.sortAs = function(other){ | 
					
						
							|  |  |  | 	return this.sort(function(a, b){ | 
					
						
							|  |  |  | 		var i = other.indexOf(a) | 
					
						
							|  |  |  | 		var j = other.indexOf(b) | 
					
						
							|  |  |  | 		return i < 0 && j < 0 ? 0 | 
					
						
							|  |  |  | 			: i < 0 ? 1 | 
					
						
							|  |  |  | 			: j < 0 ? -1 | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 			: i - j }) } | 
					
						
							| 
									
										
										
										
											2017-02-01 19:25:58 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-12 16:13:32 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | // Equivalent to .map(..) / .filter(..) / .reduce(..) / .forEach(..) that
 | 
					
						
							|  |  |  | // process the contents in chunks asynchronously...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //	.mapChunks(func)
 | 
					
						
							|  |  |  | //	.mapChunks(chunk_size, func)
 | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | //	.mapChunks([item_handler, chunk_handler])
 | 
					
						
							|  |  |  | //	.mapChunks(chunk_size, [item_handler, chunk_handler])
 | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | //		-> promise(list)
 | 
					
						
							|  |  |  | //	
 | 
					
						
							|  |  |  | //	.filterChunks(func)
 | 
					
						
							|  |  |  | //	.filterChunks(chunk_size, func)
 | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | //	.filterChunks([item_handler, chunk_handler])
 | 
					
						
							|  |  |  | //	.filterChunks(chunk_size, [item_handler, chunk_handler])
 | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | //		-> promise(list)
 | 
					
						
							|  |  |  | //	
 | 
					
						
							|  |  |  | //	.reduceChunks(func, res)
 | 
					
						
							|  |  |  | //	.reduceChunks(chunk_size, func, res)
 | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | //	.reduceChunks([item_handler, chunk_handler], res)
 | 
					
						
							|  |  |  | //	.reduceChunks(chunk_size, [item_handler, chunk_handler], res)
 | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | //		-> promise(res)
 | 
					
						
							| 
									
										
										
										
											2019-01-11 04:08:00 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | //	chunk_handler(chunk, result, offset)
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2019-01-11 04:08:00 +03:00
										 |  |  | // chunk_size can be:
 | 
					
						
							| 
									
										
										
										
											2019-04-10 04:49:35 +03:00
										 |  |  | // 	20			- chunk size
 | 
					
						
							|  |  |  | // 	'20'		- chunk size
 | 
					
						
							|  |  |  | // 	'20C'		- number of chunks
 | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | //	
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2019-01-11 04:08:00 +03:00
										 |  |  | // The main goal of this is to not block the runtime while processing a 
 | 
					
						
							|  |  |  | // very long array by interrupting the processing with a timeout...
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | var makeChunkIter = function(iter, wrapper){ | 
					
						
							|  |  |  | 	wrapper = wrapper | 
					
						
							|  |  |  | 		|| function(res, func, array, e){ | 
					
						
							|  |  |  | 			return func.call(this, e[1], e[0], array) } | 
					
						
							|  |  |  | 	return function(size, func, ...rest){ | 
					
						
							|  |  |  | 		var that = this | 
					
						
							|  |  |  | 		var args = [...arguments] | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 		size = (args[0] instanceof Function  | 
					
						
							|  |  |  | 				|| args[0] instanceof Array) ?  | 
					
						
							| 
									
										
										
										
											2019-01-11 04:17:47 +03:00
										 |  |  | 			(this.CHUNK_SIZE || 50) | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | 			: args.shift() | 
					
						
							| 
									
										
										
										
											2019-01-11 04:08:00 +03:00
										 |  |  | 		size = typeof(size) == typeof('str') ? | 
					
						
							|  |  |  | 				// number of chunks...
 | 
					
						
							| 
									
										
										
										
											2019-01-11 04:17:47 +03:00
										 |  |  | 				(size.trim().endsWith('c') || size.trim().endsWith('C') ? | 
					
						
							|  |  |  | 				 	Math.round(this.length / (parseInt(size) || 1)) || 1 | 
					
						
							| 
									
										
										
										
											2019-01-11 04:08:00 +03:00
										 |  |  | 				: parseInt(size)) | 
					
						
							|  |  |  | 			: size | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 		var postChunk | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | 		func = args.shift() | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 		;[func, postChunk] = func instanceof Array ? func : [func] | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | 		rest = args | 
					
						
							|  |  |  | 		var res = [] | 
					
						
							|  |  |  | 		var _wrapper = wrapper.bind(this, res, func, this) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return new Promise(function(resolve, reject){ | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 				var next = function(chunks){ | 
					
						
							|  |  |  | 					setTimeout(function(){ | 
					
						
							|  |  |  | 						var chunk, val | 
					
						
							|  |  |  | 						res.push( | 
					
						
							|  |  |  | 							val = (chunk = chunks.shift())[iter](_wrapper, ...rest)) | 
					
						
							|  |  |  | 						postChunk | 
					
						
							|  |  |  | 							&& postChunk.call(that,  | 
					
						
							|  |  |  | 								chunk.map(function([i, v]){ return v }),  | 
					
						
							|  |  |  | 								val, | 
					
						
							|  |  |  | 								chunk[0][0]) | 
					
						
							|  |  |  | 						// stop condition...
 | 
					
						
							|  |  |  | 						chunks.length == 0 ? | 
					
						
							|  |  |  | 							resolve(res.flat(2)) | 
					
						
							|  |  |  | 							: next(chunks) }, 0) } | 
					
						
							|  |  |  | 				next(that | 
					
						
							|  |  |  | 					// split the array into chunks...
 | 
					
						
							|  |  |  | 					.reduce(function(res, e, i){ | 
					
						
							|  |  |  | 						var c = res.slice(-1)[0] | 
					
						
							|  |  |  | 						c.length >= size ? | 
					
						
							|  |  |  | 							// initial element in chunk...
 | 
					
						
							|  |  |  | 							res.push([[i, e]]) | 
					
						
							|  |  |  | 							// rest...
 | 
					
						
							|  |  |  | 							: c.push([i, e]) | 
					
						
							|  |  |  | 						return res }, [[]])) }) } } | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-11 04:17:47 +03:00
										 |  |  | Array.prototype.CHUNK_SIZE = 50  | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | Array.prototype.mapChunks = makeChunkIter('map') | 
					
						
							|  |  |  | Array.prototype.filterChunks = makeChunkIter('map',  | 
					
						
							|  |  |  | 	function(res, func, array, e){ | 
					
						
							|  |  |  | 		return !!func.call(this, e[1], e[0], array) ? [e[1]] : [] }) | 
					
						
							|  |  |  | Array.prototype.reduceChunks = makeChunkIter('reduce', | 
					
						
							|  |  |  | 	function(total, func, array, res, e){ | 
					
						
							|  |  |  | 		return func.call(this,  | 
					
						
							|  |  |  | 			total.length > 0 ?  | 
					
						
							|  |  |  | 				total.pop()  | 
					
						
							|  |  |  | 				: res,  | 
					
						
							|  |  |  | 			e[1], e[0], array) }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-12 16:13:32 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // Set...
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-29 04:59:50 +03:00
										 |  |  | // Set set operation shorthands...
 | 
					
						
							|  |  |  | Set.prototype.unite = function(other){  | 
					
						
							|  |  |  | 	return new Set([...this, ...other]) } | 
					
						
							|  |  |  | Set.prototype.intersect = function(other){ | 
					
						
							|  |  |  | 	var test = other.has ?  'has' : 'includes' | 
					
						
							|  |  |  | 	return new Set([...this] | 
					
						
							|  |  |  | 		.filter(function(e){ return other[test](e) })) } | 
					
						
							|  |  |  | Set.prototype.subtract = function(other){ | 
					
						
							| 
									
										
										
										
											2018-12-16 05:00:11 +03:00
										 |  |  | 	other = new Set(other) | 
					
						
							| 
									
										
										
										
											2018-11-29 04:59:50 +03:00
										 |  |  | 	return new Set([...this] | 
					
						
							| 
									
										
										
										
											2018-12-16 05:00:11 +03:00
										 |  |  | 		.filter(function(e){ return !other.has(e) })) } | 
					
						
							| 
									
										
										
										
											2018-11-29 04:59:50 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-12 00:06:48 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-12 16:13:32 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // RegExp...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Quote a string and convert to RegExp to match self literally.
 | 
					
						
							|  |  |  | var quoteRegExp = | 
					
						
							|  |  |  | RegExp.quoteRegExp = | 
					
						
							|  |  |  | module.quoteRegExp = | 
					
						
							|  |  |  | function(str){ | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 	return str.replace(/([\.\\\/\(\)\[\]\$\*\+\-\{\}\@\^\&\?\<\>])/g, '\\$1') } | 
					
						
							| 
									
										
										
										
											2018-12-12 16:13:32 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // String...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | String.prototype.capitalize = function(){ | 
					
						
							|  |  |  | 	return this == '' ?  | 
					
						
							|  |  |  | 		this  | 
					
						
							|  |  |  | 		: this[0].toUpperCase() + this.slice(1) } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // Date...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NOTE: repatching a date should not lead to any side effects as this
 | 
					
						
							|  |  |  | // 		does not add any state...
 | 
					
						
							|  |  |  | var patchDate = | 
					
						
							|  |  |  | module.patchDate = function(date){ | 
					
						
							|  |  |  | 	date = date || Date | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-11 01:09:49 +03:00
										 |  |  | 	date.prototype.toShortDate = function(show_ms){ | 
					
						
							|  |  |  | 		return ''  | 
					
						
							|  |  |  | 			+ this.getFullYear() | 
					
						
							| 
									
										
										
										
											2020-04-17 17:44:03 +03:00
										 |  |  | 			+'-'+ ('0'+(this.getMonth()+1)).slice(-2) | 
					
						
							| 
									
										
										
										
											2020-04-11 01:09:49 +03:00
										 |  |  | 			+'-'+ ('0'+this.getDate()).slice(-2) | 
					
						
							|  |  |  | 			+' '+ ('0'+this.getHours()).slice(-2) | 
					
						
							|  |  |  | 			+':'+ ('0'+this.getMinutes()).slice(-2) | 
					
						
							|  |  |  | 			+':'+ ('0'+this.getSeconds()).slice(-2) | 
					
						
							|  |  |  | 			+ (show_ms ?  | 
					
						
							|  |  |  | 				':'+(('000'+this.getMilliseconds()).slice(-3)) | 
					
						
							|  |  |  | 				: '') } | 
					
						
							|  |  |  | 	date.prototype.getTimeStamp = function(show_ms){ | 
					
						
							|  |  |  | 		return ''  | 
					
						
							|  |  |  | 			+ this.getFullYear() | 
					
						
							| 
									
										
										
										
											2020-04-17 17:44:03 +03:00
										 |  |  | 			+ ('0'+(this.getMonth()+1)).slice(-2) | 
					
						
							| 
									
										
										
										
											2020-04-11 01:09:49 +03:00
										 |  |  | 			+ ('0'+this.getDate()).slice(-2) | 
					
						
							|  |  |  | 			+ ('0'+this.getHours()).slice(-2) | 
					
						
							|  |  |  | 			+ ('0'+this.getMinutes()).slice(-2) | 
					
						
							|  |  |  | 			+ ('0'+this.getSeconds()).slice(-2) | 
					
						
							|  |  |  | 			+ (show_ms ?  | 
					
						
							|  |  |  | 				('000'+this.getMilliseconds()).slice(-3) | 
					
						
							|  |  |  | 				: '') } | 
					
						
							| 
									
										
										
										
											2018-12-12 16:13:32 +03:00
										 |  |  | 	date.prototype.setTimeStamp = function(ts){ | 
					
						
							|  |  |  | 		ts = ts.replace(/[^0-9]*/g, '') | 
					
						
							|  |  |  | 		this.setFullYear(ts.slice(0, 4)) | 
					
						
							|  |  |  | 		this.setMonth(ts.slice(4, 6)*1-1) | 
					
						
							|  |  |  | 		this.setDate(ts.slice(6, 8)) | 
					
						
							|  |  |  | 		this.setHours(ts.slice(8, 10)) | 
					
						
							|  |  |  | 		this.setMinutes(ts.slice(10, 12)) | 
					
						
							|  |  |  | 		this.setSeconds(ts.slice(12, 14)) | 
					
						
							| 
									
										
										
										
											2020-04-11 01:09:49 +03:00
										 |  |  | 		this.setMilliseconds(ts.slice(14, 17) || 0) | 
					
						
							|  |  |  | 		return this } | 
					
						
							|  |  |  | 	date.timeStamp = function(...args){ | 
					
						
							|  |  |  | 		return (new this()).getTimeStamp(...args) } | 
					
						
							| 
									
										
										
										
											2018-12-12 16:13:32 +03:00
										 |  |  | 	date.fromTimeStamp = function(ts){ | 
					
						
							| 
									
										
										
										
											2020-04-11 01:09:49 +03:00
										 |  |  | 		return (new this()).setTimeStamp(ts) } | 
					
						
							| 
									
										
										
										
											2018-12-12 16:13:32 +03:00
										 |  |  | 	// convert string time period to milliseconds...
 | 
					
						
							|  |  |  | 	date.str2ms = function(str, dfl){ | 
					
						
							|  |  |  | 		dfl = dfl || 'ms' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(typeof(str) == typeof(123)){ | 
					
						
							|  |  |  | 			var val = str | 
					
						
							|  |  |  | 			str = dfl | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			var val = parseFloat(str) | 
					
						
							|  |  |  | 			str = str.trim() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// check if a unit is given...
 | 
					
						
							|  |  |  | 			str = str == val ? dfl : str | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		var c = /(m(illi)?(-)?s(ec(ond(s)?)?)?)$/i.test(str) ? 1 | 
					
						
							|  |  |  | 			: /s(ec(ond(s)?)?)?$/i.test(str) ? 1000 | 
					
						
							|  |  |  | 			: /m(in(ute(s)?)?)?$/i.test(str) ? 1000*60 | 
					
						
							|  |  |  | 			: /h(our(s)?)?$/i.test(str) ? 1000*60*60 | 
					
						
							|  |  |  | 			: /d(ay(s)?)?$/i.test(str) ? 1000*60*60*24 | 
					
						
							|  |  |  | 			: null | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return c ? val * c : NaN | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return date | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | // patch the root date...
 | 
					
						
							|  |  |  | patchDate() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // Misc...
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-20 16:17:12 +03:00
										 |  |  | module.chainCmp = function(cmp_chain){ | 
					
						
							|  |  |  | 	return function(a, b, get, data){ | 
					
						
							|  |  |  | 		var res | 
					
						
							|  |  |  | 		for(var i=0; i < cmp_chain.length; i++){ | 
					
						
							|  |  |  | 			res = cmp_chain[i](a, b, get, data) | 
					
						
							|  |  |  | 			if(res != 0){ | 
					
						
							|  |  |  | 				return res | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return res | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }  | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-31 10:37:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 09:14:59 +03:00
										 |  |  | // XXX do we need to quote anything else???
 | 
					
						
							|  |  |  | var path2url = | 
					
						
							|  |  |  | module.path2url = | 
					
						
							|  |  |  | function(path){ | 
					
						
							|  |  |  | 	// test if we have a schema, and if yes return as-is...
 | 
					
						
							| 
									
										
										
										
											2017-06-16 19:41:27 +03:00
										 |  |  | 	if(/^(data|http|https|file|[\w-]*):[\\\/]{2}/.test(path)){ | 
					
						
							| 
									
										
										
										
											2015-12-17 09:14:59 +03:00
										 |  |  | 		return path | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// skip encoding windows drives...
 | 
					
						
							| 
									
										
										
										
											2017-06-17 06:33:47 +03:00
										 |  |  | 	path = path | 
					
						
							| 
									
										
										
										
											2015-12-17 09:14:59 +03:00
										 |  |  | 		.split(/[\\\/]/g) | 
					
						
							| 
									
										
										
										
											2017-06-17 06:33:47 +03:00
										 |  |  | 	drive = path[0].endsWith(':') ? | 
					
						
							|  |  |  | 		path.shift() + '/' | 
					
						
							|  |  |  | 		: '' | 
					
						
							|  |  |  | 	return drive + (path | 
					
						
							| 
									
										
										
										
											2015-12-17 09:14:59 +03:00
										 |  |  | 		// XXX these are too aggressive...
 | 
					
						
							|  |  |  | 		//.map(encodeURI)
 | 
					
						
							|  |  |  | 		//.map(encodeURIComponent)
 | 
					
						
							|  |  |  | 		.join('/') | 
					
						
							|  |  |  | 		// NOTE: keep '%' the first...
 | 
					
						
							| 
									
										
										
										
											2017-11-17 02:45:44 +03:00
										 |  |  | 		.replace(/%/g, '%25') | 
					
						
							| 
									
										
										
										
											2015-12-17 09:14:59 +03:00
										 |  |  | 		.replace(/#/g, '%23') | 
					
						
							|  |  |  | 		.replace(/&/g, '%26')) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | // NOTE: we are not using node's path module as we need this to work in
 | 
					
						
							|  |  |  | // 		all contexts, not only node... (???)
 | 
					
						
							|  |  |  | var normalizePath =  | 
					
						
							|  |  |  | module.normalizePath = | 
					
						
							|  |  |  | function(path){ | 
					
						
							|  |  |  | 	return typeof(path) == typeof('str') ? path | 
					
						
							|  |  |  | 			// normalize the slashes...
 | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 			.replace(/\\/g, '/') | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 			// remove duplicate '/'
 | 
					
						
							|  |  |  | 			.replace(/(\/)\1+/g, '/') | 
					
						
							|  |  |  | 			// remove trailing '/'
 | 
					
						
							|  |  |  | 			.replace(/\/+$/, '') | 
					
						
							|  |  |  | 			// take care of .
 | 
					
						
							|  |  |  | 			.replace(/\/\.\//g, '/') | 
					
						
							|  |  |  | 			.replace(/\/\.$/, '') | 
					
						
							|  |  |  | 			// take care of ..
 | 
					
						
							|  |  |  | 			.replace(/\/[^\/]+\/\.\.\//g, '/') | 
					
						
							|  |  |  | 			.replace(/\/[^\/]+\/\.\.$/, '') | 
					
						
							|  |  |  | 		: path | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-14 16:01:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | /********************************************************************** | 
					
						
							| 
									
										
										
										
											2016-08-20 22:49:36 +03:00
										 |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |