UNPKG

art-standard-lib

Version:

The Standard Library for JavaScript that aught to be.

380 lines (323 loc) 10.8 kB
// Generated by CoffeeScript 1.12.7 (function() { var Core, Types, isFunction, isJsonAtomicType, isObject, isPlainArray, isPlainObject, isString, mergeInto, ref; ref = Core = require('./Core'), isPlainObject = ref.isPlainObject, mergeInto = ref.mergeInto, isString = ref.isString, isFunction = ref.isFunction, isObject = ref.isObject, isPlainArray = ref.isPlainArray, isJsonAtomicType = ref.isJsonAtomicType; module.exports = Types = (function() { var cloneObjectUpToKey, deepEach, deepEachAll, deepMap, deepMapArray, deepMapObject, functionName, noopMapper, objectName, stringIsPresent, tEq, throwInequalityError, toJsonStructure, toPostMessageStructure; function Types() {} mergeInto(Types, Core.Types); throwInequalityError = function(a, b) { throw new Error("Value types are not compatible for inequality tests. a: " + (a != null ? a.constructor.name : void 0) + ", b: " + (b != null ? b.constructor.name : void 0)); }; /* * simplified - as simple as I can make it * sacrifices some semantics gt = (a, b)-> if (o = a > b) || a <= b return o a.gt b * just a tad more complex and only sacrifices clear errors gt = (a, b)-> if typeof a == typeof b if (o = a > b) || a <= b return o a.gt b */ tEq = function(a, b) { return typeof a === typeof b; }; Types.gt = function(a, b) { var s; if ((a != null) && (b != null)) { s = tEq(a, b); return (s && a > b) || ((s && a <= b) ? false : a.gt(b)); } else { return throwInequalityError(a, b); } }; Types.lt = function(a, b) { var s; if ((a != null) && (b != null)) { s = tEq(a, b); return (s && a < b) || ((s && a >= b) ? false : a.lt(b)); } else { return throwInequalityError(a, b); } }; Types.gte = function(a, b) { var s; if ((a != null) && (b != null)) { s = tEq(a, b); return (s && a >= b) || ((s && a < b) ? false : a.gte(b)); } else { return throwInequalityError(a, b); } }; Types.lte = function(a, b) { var s; if ((a != null) && (b != null)) { s = tEq(a, b); return (s && a <= b) || ((s && a > b) ? false : a.lte(b)); } else { return throwInequalityError(a, b); } }; /* like RubyOnRails#present: "An object is present if it's not blank." basic: present null, undefined, false or "" returns false (or whatever returnIfNotPresent is set to) all other values return something truish - generally themselves Yes, in ruby/rails, present(false) == false. Though logically true, I've also found it lead to unexpected results in production code. I had a false-value where I was expecting a string due to a corrupted database value. Possible argment for present(false) == false: It's easy to accidentally return false when you meant to return null or undefined. I think this is how my database got the corrupted false-instead-of null-value. Another argument: present(x) should always be false if x is false. custom: for bar where isFunction bar.present present bar returns bar.present() special-case truish results: present 0 or false returns true for any other value foo, present foo returns foo IN: obj: object tested for presence returnIfNotPresent: [false] what to return if not present OUT: returnIfNotPresent, true, or the value passed in If 'obj' has method: obj.present() => obj.present() */ Types.present = function(obj, returnIfNotPresent) { var present; if (returnIfNotPresent == null) { returnIfNotPresent = false; } present = isFunction(obj != null ? obj.getPresent : void 0) ? obj.getPresent() : isFunction(obj != null ? obj.present : void 0) ? obj.present() : isString(obj) ? stringIsPresent(obj) : obj !== void 0 && obj !== null && obj !== false; if (present) { return obj || true; } else { return returnIfNotPresent; } }; Types.stringIsPresent = stringIsPresent = function(str) { return isString(str) && !/^(\s+|)$/.test(str); }; Types.functionName = functionName = function(f) { var matched; return f.name || ((matched = ("" + f).match(/function ([a-zA-Z]+)\(/)) && matched[1]) || "function"; }; Types.objectName = objectName = function(obj) { var a, name, ref1; if (!obj) { return "" + obj; } else if (a = typeof obj.getNamespacePath === "function" ? obj.getNamespacePath() : void 0) { return a; } else if (a = obj.classPathName) { return a; } else if (obj.constructor === Object) { return "Object"; } else if (isFunction(obj)) { return functionName(obj); } else if (isString(name = (ref1 = obj.constructor) != null ? ref1.name : void 0) && name.length > 0) { return name; } else if (obj instanceof Object) { return "(anonymous instanceof Object)"; } else { return "(objectName unknown)"; } }; Types.isBrowserObject = function(obj) { var name; if (!Types.isObject(obj)) { return false; } name = Types.objectName(obj); return name.slice(0, 4) === "HTML" || name.slice(0, 22) === "CanvasRenderingContext"; }; /* IN: f: (value, [key]) -> f is called on every non-plainObject and non-plainArray reachable by traversing the plainObject/plainArray structure If f is called on a propery of a plainObject, the key for that property is also passed in. OUT: value */ Types.deepEach = deepEach = function(v, f, key) { var j, k, len, subV; if (isPlainArray(v)) { for (j = 0, len = v.length; j < len; j++) { subV = v[j]; deepEach(subV, f); } } else if (isPlainObject(v)) { for (k in v) { subV = v[k]; deepEach(subV, f, k); } } else { f(v, key); } return v; }; /* deepEachAll: just like deepEach except 'f' gets called on every value found including the initial value. */ Types.deepEachAll = deepEachAll = function(v, f, key) { var j, k, len, subV; f(v, key); if (isPlainArray(v)) { for (j = 0, len = v.length; j < len; j++) { subV = v[j]; deepEachAll(subV, f); } } else if (isPlainObject(v)) { for (k in v) { subV = v[k]; deepEachAll(subV, f, k); } } else { } return v; }; /* only creates a new array if the children changed */ deepMapArray = function(array, mapper, options) { var i, j, len, p, r, res, v; res = null; for (i = j = 0, len = array.length; j < len; i = ++j) { v = array[i]; r = deepMap(v, mapper, options); if (r !== v) { res || (res = array.slice()); res[i] = r; } } res || (res = array); if (p = options != null ? options.postprocessArray : void 0) { return p(res); } else { return res; } }; cloneObjectUpToKey = function(obj, k) { var k2, res, v; res = {}; for (k2 in obj) { v = obj[k2]; if (k2 === k) { break; } res[k2] = v; } return res; }; deepMapObject = function(obj, mapper, options) { var k, p, r, res, v; res = null; for (k in obj) { v = obj[k]; r = deepMap(v, mapper, options); if (r !== v || res) { res || (res = cloneObjectUpToKey(obj, k)); res[k] = r; } } res || (res = obj); if (p = options != null ? options.postprocessObject : void 0) { return p(res); } else { return res; } }; noopMapper = function(v) { return v; }; /* Applies "f" to every -value- in a nested structure of plain arrays and objects. Pure functional efficient: If an array or object, and all its sub values, didn't change, the original array/object is reused. NOTE: deepMap only yields values to 'mapper' which are NOT plain arrays nor plain objects. */ Types.deepMap = deepMap = function(v, mapper, options) { var arrayMapper, objectMapper; arrayMapper = (options != null ? options.arrays : void 0) || noopMapper; objectMapper = (options != null ? options.objects : void 0) || noopMapper; mapper || (mapper = noopMapper); if (isPlainArray(v)) { return deepMapArray(arrayMapper(v), mapper, options); } else if (isPlainObject(v)) { return deepMapObject(objectMapper(v), mapper, options); } else { return mapper(v); } }; Types.toPlainStructure = function(o) { return deepMap(o, function(o) { if (isObject(o)) { if (o.toPlainStructure) { return o.toPlainStructure(); } else { return objectName(o); } } else { return o; } }); }; /* similar to toPlainStructure, except all non-JSON types are converted to strings */ Types.toJsonStructure = toJsonStructure = function(o) { return deepMap(o, function(o) { if (isObject(o)) { if (o.toJsonStructure) { return o.toJsonStructure(); } else { return toJsonStructure(o.toPlainStructure ? o.toPlainStructure() : "" + o); } } else if (isJsonAtomicType(o)) { return o; } else { return "" + o; } }); }; Types.toPostMessageStructure = toPostMessageStructure = function(o) { return deepMap(o, function(o) { switch (o.constructor) { case ArrayBuffer: case Date: case RegExp: case Blob: case File: case FileList: case ImageData: case Boolean: case String: return o; default: if (isObject(o)) { if (o.toPostMessageStructure) { return o.toPostMessageStructure(); } else { if (o.toPlainStructure) { return toPostMessageStructure(o.toPlainStructure()); } else { return "" + o; } } } else { return "" + o; } } }); }; return Types; })(); }).call(this); //# sourceMappingURL=TypesExtended.js.map