Skip to content

Commit

Permalink
Merge pull request #25 from spenceralger/saved_search
Browse files Browse the repository at this point in the history
Saved search
  • Loading branch information
spenceralger committed Mar 24, 2014
2 parents 3b6762e + e7eb964 commit 9f2a028
Show file tree
Hide file tree
Showing 28 changed files with 1,336 additions and 330 deletions.
13 changes: 13 additions & 0 deletions src/bower_components/jsonpath/.bower.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "jsonpath",
"homepage": "https://github.com/s3u/JSONPath",
"_release": "308ef21860",
"_resolution": {
"type": "branch",
"branch": "master",
"commit": "308ef21860ae21584c0f808d67cf63006101149a"
},
"_source": "git://github.com/s3u/JSONPath.git",
"_target": "*",
"_originalSource": "jsonpath"
}
9 changes: 9 additions & 0 deletions src/bower_components/jsonpath/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
*.iml
.DS_Store
.idea
temp
node_modules
pids
reports
target
*.log
2 changes: 2 additions & 0 deletions src/bower_components/jsonpath/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
test
4 changes: 4 additions & 0 deletions src/bower_components/jsonpath/.travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
language: node_js
node_js:
- 0.6
- 0.8
14 changes: 14 additions & 0 deletions src/bower_components/jsonpath/CHANGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

## Oct 23, 2013

* Support for parent selection via `^`
* Access current path via `@path` in test statements
* Allowing for multi-statement evals
* Performance improvements
* Version 0.10

## Mar 28, 2012

* Support a sandbox arg to eval
* Use vm.runInNewContext in place of eval
* Version 0.9.0
111 changes: 111 additions & 0 deletions src/bower_components/jsonpath/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
JSONPath [![build status](https://secure.travis-ci.org/s3u/JSONPath.png)](http://travis-ci.org/s3u/JSONPath)
========

Analyse, transform, and selectively extract data from JSON documents (and JavaScript objects).

Install
-------

npm install JSONPath

Usage
-----

In node.js:

```js
var jsonPath = require('JSONPath');
jsonPath.eval(obj, path);
```

For browser usage you can directly include `lib/jsonpath.js`, no browserify
magic necessary:

```html
<script type="text/javascript" src="lib/jsonpath.js"></script>
<script type="text/javascript">
jsonPath.eval(obj, path);
</script>
```

Examples
--------

Given the following JSON, taken from http://goessner.net/articles/JsonPath/ :

```json
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
```


XPath | JSONPath | Result
------------------- | ---------------------- | -------------------------------------
/store/book/author | $.store.book[*].author | the authors of all books in the store
//author | $..author | all authors
/store/* | $.store.* | all things in store, which are some books and a red bicycle.
/store//price | $.store..price | the price of everything in the store.
//book[3] | $..book[2] | the third book
//book[last()] | $..book[(@.length-1)] | the last book in order.
| $..book[-1:] |
//book[position()<3]| $..book[0,1] | the first two books
| $..book[:2] |
//book[isbn] | $..book[?(@.isbn)] | filter all books with isbn number
//book[price<10] | $..book[?(@.price<10)] | filter all books cheapier than 10
//*[price>19]/.. | $..[?(@.price>19)]^ | categories with things more expensive than 19
//* | $..* | all Elements in XML document. All members of JSON structure.

Development
-----------

Running the tests on node: `npm test`. For in-browser tests:

* Ensure that nodeunit is browser-compiled: `cd node_modules/nodeunit; make browser;`
* Serve the js/html files:

```sh
node -e "require('http').createServer(function(req,res) { \
var s = require('fs').createReadStream('.' + req.url); \
s.pipe(res); s.on('error', function() {}); }).listen(8082);"
```
* To run the tests visit [http://localhost:8082/test/test.html]().


License
-------

[MIT License](http://www.opensource.org/licenses/mit-license.php).
172 changes: 172 additions & 0 deletions src/bower_components/jsonpath/lib/jsonpath.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
/* JSONPath 0.8.0 - XPath for JSON
*
* Copyright (c) 2007 Stefan Goessner (goessner.net)
* Licensed under the MIT (MIT-LICENSE.txt) licence.
*/

var isNode = false;
(function(exports, require) {

// Keep compatibility with old browsers
if (!Array.isArray) {
Array.isArray = function(vArg) {
return Object.prototype.toString.call(vArg) === "[object Array]";
};
}

// Make sure to know if we are in real node or not (the `require` variable
// could actually be require.js, for example.
var isNode = typeof module !== 'undefined' && !!module.exports;

var vm = isNode ?
require('vm') : {
runInNewContext: function(expr, context) { with (context) return eval(expr); }
};
exports.eval = jsonPath;

var cache = {};

function push(arr, elem) { arr = arr.slice(); arr.push(elem); return arr; }
function unshift(elem, arr) { arr = arr.slice(); arr.unshift(elem); return arr; }

function jsonPath(obj, expr, arg) {
var P = {
resultType: arg && arg.resultType || "VALUE",
flatten: arg && arg.flatten || false,
wrap: (arg && arg.hasOwnProperty('wrap')) ? arg.wrap : true,
sandbox: (arg && arg.sandbox) ? arg.sandbox : {},
normalize: function(expr) {
if (cache[expr]) return cache[expr];
var subx = [];
var normalized = expr.replace(/[\['](\??\(.*?\))[\]']/g, function($0,$1){return "[#"+(subx.push($1)-1)+"]";})
.replace(/'?\.'?|\['?/g, ";")
.replace(/(;)?(\^+)(;)?/g, function(_, front, ups, back) { return ';' + ups.split('').join(';') + ';'; })
.replace(/;;;|;;/g, ";..;")
.replace(/;$|'?\]|'$/g, "");
var exprList = normalized.split(';').map(function(expr) {
var match = expr.match(/#([0-9]+)/);
return !match || !match[1] ? expr : subx[match[1]];
})
return cache[expr] = exprList;
},
asPath: function(path) {
var x = path, p = "$";
for (var i=1,n=x.length; i<n; i++)
p += /^[0-9*]+$/.test(x[i]) ? ("["+x[i]+"]") : ("['"+x[i]+"']");
return p;
},
trace: function(expr, val, path) {
// no expr to follow? return path and value as the result of this trace branch
if (!expr.length) return [{path: path, value: val}];

var loc = expr[0], x = expr.slice(1);
// the parent sel computation is handled in the frame above using the
// ancestor object of val
if (loc === '^') return path.length ? [{path: path.slice(0,-1), expr: x, isParentSelector: true}] : [];

// we need to gather the return value of recursive trace calls in order to
// do the parent sel computation.
var ret = [];
function addRet(elems) { ret = ret.concat(elems); }

if (val && val.hasOwnProperty(loc)) // simple case, directly follow property
addRet(P.trace(x, val[loc], push(path, loc)));
else if (loc === "*") { // any property
P.walk(loc, x, val, path, function(m,l,x,v,p) {
addRet(P.trace(unshift(m, x), v, p)); });
}
else if (loc === "..") { // all chid properties
addRet(P.trace(x, val, path));
P.walk(loc, x, val, path, function(m,l,x,v,p) {
if (typeof v[m] === "object")
addRet(P.trace(unshift("..", x), v[m], push(p, m)));
});
}
else if (loc[0] === '(') { // [(expr)]
addRet(P.trace(unshift(P.eval(loc, val, path[path.length], path),x), val, path));
}
else if (loc.indexOf('?(') === 0) { // [?(expr)]
P.walk(loc, x, val, path, function(m,l,x,v,p) {
if (P.eval(l.replace(/^\?\((.*?)\)$/,"$1"),v[m],m, path))
addRet(P.trace(unshift(m,x),v,p));
});
}
else if (loc.indexOf(',') > -1) { // [name1,name2,...]
for (var parts = loc.split(','), i = 0; i < parts.length; i++)
addRet(P.trace(unshift(parts[i], x), val, path));
}
else if (/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(loc)) { // [start:end:step] python slice syntax
addRet(P.slice(loc, x, val, path));
}

// we check the resulting values for parent selections. for parent
// selections we discard the value object and continue the trace with the
// current val object
return ret.reduce(function(all, ea) {
return all.concat(ea.isParentSelector ? P.trace(ea.expr, val, ea.path) : [ea]);
}, []);
},
walk: function(loc, expr, val, path, f) {
if (Array.isArray(val))
for (var i = 0, n = val.length; i < n; i++)
f(i, loc, expr, val, path);
else if (typeof val === "object")
for (var m in val)
if (val.hasOwnProperty(m))
f(m, loc, expr, val, path);
},
slice: function(loc, expr, val, path) {
if (!Array.isArray(val)) return;
var len = val.length, parts = loc.split(':'),
start = (parts[0] && parseInt(parts[0])) || 0,
end = (parts[1] && parseInt(parts[1])) || len,
step = (parts[2] && parseInt(parts[2])) || 1;
start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start);
end = (end < 0) ? Math.max(0,end+len) : Math.min(len,end);
var ret = [];
for (var i = start; i < end; i += step)
ret = ret.concat(P.trace(unshift(i,expr), val, path));
return ret;
},
eval: function(code, _v, _vname, path) {
if (!$ || !_v) return false;
if (code.indexOf("@path") > -1) {
P.sandbox["_path"] = P.asPath(path.concat([_vname]));
code = code.replace(/@path/g, "_path");
}
if (code.indexOf("@") > -1) {
P.sandbox["_v"] = _v;
code = code.replace(/@/g, "_v");
}
try {
return vm.runInNewContext(code, P.sandbox);
}
catch(e) {
console.log(e);
throw new Error("jsonPath: " + e.message + ": " + code);
}
}
};

var $ = obj;
var resultType = P.resultType.toLowerCase();
if (expr && obj && (resultType == "value" || resultType == "path")) {
var exprList = P.normalize(expr);
if (exprList[0] === "$" && exprList.length > 1) exprList.shift();
var result = P.trace(exprList, obj, ["$"]);
result = result.filter(function(ea) { return ea && !ea.isParentSelector; });
if (!result.length) return P.wrap ? [] : false;
if (result.length === 1 && !P.wrap && !Array.isArray(result[0].value)) return result[0][resultType] || false;
return result.reduce(function(result, ea) {
var valOrPath = ea[resultType];
if (resultType === 'path') valOrPath = P.asPath(valOrPath);
if (P.flatten && Array.isArray(valOrPath)) {
result = result.concat(valOrPath);
} else {
result.push(valOrPath);
}
return result;
}, []);
}
}
})(typeof exports === 'undefined' ? this['jsonPath'] = {} : exports, typeof require == "undefined" ? null : require);
36 changes: 36 additions & 0 deletions src/bower_components/jsonpath/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"author": "Stefan Goessner",
"name": "JSONPath",
"description": "A JS implementation of JSONPath",
"contributors": [
{
"name": "Prof. Gössner",
"email": "[email protected]"
},
{
"name": "Subbu Allamaraju",
"email": "[email protected]"
},
{
"name": "Mike Brevoort",
"email": "[email protected]"
},
{
"name": "Robert Krahn",
"email": "[email protected]"
}
],
"version": "0.10.0",
"repository": {
"type": "git",
"url": "git://github.com/s3u/JSONPath.git"
},
"main": "./lib/jsonpath",
"dependencies": {
"underscore": "*"
},
"devDependencies": {
"nodeunit": "*"
},
"scripts": {"test": "node_modules/nodeunit/bin/nodeunit test/test.*.js"}
}
Loading

0 comments on commit 9f2a028

Please sign in to comment.