art-standard-lib
Version:
The Standard Library for JavaScript that aught to be.
380 lines (323 loc) • 10.8 kB
JavaScript
// 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