added unit testing, and started implementing unit tests...phew
This commit is contained in:
291
node_modules/pathval/index.js
generated
vendored
Normal file
291
node_modules/pathval/index.js
generated
vendored
Normal file
@ -0,0 +1,291 @@
|
||||
'use strict';
|
||||
|
||||
/* !
|
||||
* Chai - pathval utility
|
||||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||||
* @see https://github.com/logicalparadox/filtr
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* ### .hasProperty(object, name)
|
||||
*
|
||||
* This allows checking whether an object has own
|
||||
* or inherited from prototype chain named property.
|
||||
*
|
||||
* Basically does the same thing as the `in`
|
||||
* operator but works properly with null/undefined values
|
||||
* and other primitives.
|
||||
*
|
||||
* var obj = {
|
||||
* arr: ['a', 'b', 'c']
|
||||
* , str: 'Hello'
|
||||
* }
|
||||
*
|
||||
* The following would be the results.
|
||||
*
|
||||
* hasProperty(obj, 'str'); // true
|
||||
* hasProperty(obj, 'constructor'); // true
|
||||
* hasProperty(obj, 'bar'); // false
|
||||
*
|
||||
* hasProperty(obj.str, 'length'); // true
|
||||
* hasProperty(obj.str, 1); // true
|
||||
* hasProperty(obj.str, 5); // false
|
||||
*
|
||||
* hasProperty(obj.arr, 'length'); // true
|
||||
* hasProperty(obj.arr, 2); // true
|
||||
* hasProperty(obj.arr, 3); // false
|
||||
*
|
||||
* @param {Object} object
|
||||
* @param {String|Symbol} name
|
||||
* @returns {Boolean} whether it exists
|
||||
* @namespace Utils
|
||||
* @name hasProperty
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function hasProperty(obj, name) {
|
||||
if (typeof obj === 'undefined' || obj === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The `in` operator does not work with primitives.
|
||||
return name in Object(obj);
|
||||
}
|
||||
|
||||
/* !
|
||||
* ## parsePath(path)
|
||||
*
|
||||
* Helper function used to parse string object
|
||||
* paths. Use in conjunction with `internalGetPathValue`.
|
||||
*
|
||||
* var parsed = parsePath('myobject.property.subprop');
|
||||
*
|
||||
* ### Paths:
|
||||
*
|
||||
* * Can be infinitely deep and nested.
|
||||
* * Arrays are also valid using the formal `myobject.document[3].property`.
|
||||
* * Literal dots and brackets (not delimiter) must be backslash-escaped.
|
||||
*
|
||||
* @param {String} path
|
||||
* @returns {Object} parsed
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function parsePath(path) {
|
||||
var str = path.replace(/([^\\])\[/g, '$1.[');
|
||||
var parts = str.match(/(\\\.|[^.]+?)+/g);
|
||||
return parts.map(function mapMatches(value) {
|
||||
var regexp = /^\[(\d+)\]$/;
|
||||
var mArr = regexp.exec(value);
|
||||
var parsed = null;
|
||||
if (mArr) {
|
||||
parsed = { i: parseFloat(mArr[1]) };
|
||||
} else {
|
||||
parsed = { p: value.replace(/\\([.\[\]])/g, '$1') };
|
||||
}
|
||||
|
||||
return parsed;
|
||||
});
|
||||
}
|
||||
|
||||
/* !
|
||||
* ## internalGetPathValue(obj, parsed[, pathDepth])
|
||||
*
|
||||
* Helper companion function for `.parsePath` that returns
|
||||
* the value located at the parsed address.
|
||||
*
|
||||
* var value = getPathValue(obj, parsed);
|
||||
*
|
||||
* @param {Object} object to search against
|
||||
* @param {Object} parsed definition from `parsePath`.
|
||||
* @param {Number} depth (nesting level) of the property we want to retrieve
|
||||
* @returns {Object|Undefined} value
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function internalGetPathValue(obj, parsed, pathDepth) {
|
||||
var temporaryValue = obj;
|
||||
var res = null;
|
||||
pathDepth = (typeof pathDepth === 'undefined' ? parsed.length : pathDepth);
|
||||
|
||||
for (var i = 0; i < pathDepth; i++) {
|
||||
var part = parsed[i];
|
||||
if (temporaryValue) {
|
||||
if (typeof part.p === 'undefined') {
|
||||
temporaryValue = temporaryValue[part.i];
|
||||
} else {
|
||||
temporaryValue = temporaryValue[part.p];
|
||||
}
|
||||
|
||||
if (i === (pathDepth - 1)) {
|
||||
res = temporaryValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* !
|
||||
* ## internalSetPathValue(obj, value, parsed)
|
||||
*
|
||||
* Companion function for `parsePath` that sets
|
||||
* the value located at a parsed address.
|
||||
*
|
||||
* internalSetPathValue(obj, 'value', parsed);
|
||||
*
|
||||
* @param {Object} object to search and define on
|
||||
* @param {*} value to use upon set
|
||||
* @param {Object} parsed definition from `parsePath`
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function internalSetPathValue(obj, val, parsed) {
|
||||
var tempObj = obj;
|
||||
var pathDepth = parsed.length;
|
||||
var part = null;
|
||||
// Here we iterate through every part of the path
|
||||
for (var i = 0; i < pathDepth; i++) {
|
||||
var propName = null;
|
||||
var propVal = null;
|
||||
part = parsed[i];
|
||||
|
||||
// If it's the last part of the path, we set the 'propName' value with the property name
|
||||
if (i === (pathDepth - 1)) {
|
||||
propName = typeof part.p === 'undefined' ? part.i : part.p;
|
||||
// Now we set the property with the name held by 'propName' on object with the desired val
|
||||
tempObj[propName] = val;
|
||||
} else if (typeof part.p !== 'undefined' && tempObj[part.p]) {
|
||||
tempObj = tempObj[part.p];
|
||||
} else if (typeof part.i !== 'undefined' && tempObj[part.i]) {
|
||||
tempObj = tempObj[part.i];
|
||||
} else {
|
||||
// If the obj doesn't have the property we create one with that name to define it
|
||||
var next = parsed[i + 1];
|
||||
// Here we set the name of the property which will be defined
|
||||
propName = typeof part.p === 'undefined' ? part.i : part.p;
|
||||
// Here we decide if this property will be an array or a new object
|
||||
propVal = typeof next.p === 'undefined' ? [] : {};
|
||||
tempObj[propName] = propVal;
|
||||
tempObj = tempObj[propName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ### .getPathInfo(object, path)
|
||||
*
|
||||
* This allows the retrieval of property info in an
|
||||
* object given a string path.
|
||||
*
|
||||
* The path info consists of an object with the
|
||||
* following properties:
|
||||
*
|
||||
* * parent - The parent object of the property referenced by `path`
|
||||
* * name - The name of the final property, a number if it was an array indexer
|
||||
* * value - The value of the property, if it exists, otherwise `undefined`
|
||||
* * exists - Whether the property exists or not
|
||||
*
|
||||
* @param {Object} object
|
||||
* @param {String} path
|
||||
* @returns {Object} info
|
||||
* @namespace Utils
|
||||
* @name getPathInfo
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function getPathInfo(obj, path) {
|
||||
var parsed = parsePath(path);
|
||||
var last = parsed[parsed.length - 1];
|
||||
var info = {
|
||||
parent: parsed.length > 1 ? internalGetPathValue(obj, parsed, parsed.length - 1) : obj,
|
||||
name: last.p || last.i,
|
||||
value: internalGetPathValue(obj, parsed),
|
||||
};
|
||||
info.exists = hasProperty(info.parent, info.name);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* ### .getPathValue(object, path)
|
||||
*
|
||||
* This allows the retrieval of values in an
|
||||
* object given a string path.
|
||||
*
|
||||
* var obj = {
|
||||
* prop1: {
|
||||
* arr: ['a', 'b', 'c']
|
||||
* , str: 'Hello'
|
||||
* }
|
||||
* , prop2: {
|
||||
* arr: [ { nested: 'Universe' } ]
|
||||
* , str: 'Hello again!'
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* The following would be the results.
|
||||
*
|
||||
* getPathValue(obj, 'prop1.str'); // Hello
|
||||
* getPathValue(obj, 'prop1.att[2]'); // b
|
||||
* getPathValue(obj, 'prop2.arr[0].nested'); // Universe
|
||||
*
|
||||
* @param {Object} object
|
||||
* @param {String} path
|
||||
* @returns {Object} value or `undefined`
|
||||
* @namespace Utils
|
||||
* @name getPathValue
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function getPathValue(obj, path) {
|
||||
var info = getPathInfo(obj, path);
|
||||
return info.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* ### .setPathValue(object, path, value)
|
||||
*
|
||||
* Define the value in an object at a given string path.
|
||||
*
|
||||
* ```js
|
||||
* var obj = {
|
||||
* prop1: {
|
||||
* arr: ['a', 'b', 'c']
|
||||
* , str: 'Hello'
|
||||
* }
|
||||
* , prop2: {
|
||||
* arr: [ { nested: 'Universe' } ]
|
||||
* , str: 'Hello again!'
|
||||
* }
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
* The following would be acceptable.
|
||||
*
|
||||
* ```js
|
||||
* var properties = require('tea-properties');
|
||||
* properties.set(obj, 'prop1.str', 'Hello Universe!');
|
||||
* properties.set(obj, 'prop1.arr[2]', 'B');
|
||||
* properties.set(obj, 'prop2.arr[0].nested.value', { hello: 'universe' });
|
||||
* ```
|
||||
*
|
||||
* @param {Object} object
|
||||
* @param {String} path
|
||||
* @param {Mixed} value
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function setPathValue(obj, path, val) {
|
||||
var parsed = parsePath(path);
|
||||
internalSetPathValue(obj, val, parsed);
|
||||
return obj;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
hasProperty: hasProperty,
|
||||
getPathInfo: getPathInfo,
|
||||
getPathValue: getPathValue,
|
||||
setPathValue: setPathValue,
|
||||
};
|
Reference in New Issue
Block a user