Socket
Socket
Sign inDemoInstall

js-select

Package Overview
Dependencies
2
Maintainers
0
Versions
7
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.2.0 to 0.4.0

contains.diff

134

index.js
var traverse = require("traverse"),
JSONSelect = require("JSONSelect");
module.exports = function(obj, sel) {
sel = sel || "*";
module.exports = function(obj, string) {
sels = parseSelectors(string);

@@ -18,5 +18,5 @@ return {

traverse(obj).forEach(function(node) {
if (isMatch(sel, this)) {
this.matches = function(sel) {
return isMatch(sel, this);
if (matchesAny(sels, this)) {
this.matches = function(string) {
return matchesAny(parseSelectors(string), this);
};

@@ -31,18 +31,36 @@ // inherit context from js-traverse

function isMatch(sel, context) {
var parts = JSONSelect._parse(sel)[1],
path = traverse.clone(context.path),
i = 0;
parts.reverse();
path.reverse();
path.push("");
function parseSelectors(string) {
var parsed = JSONSelect._parse(string || "*")[1];
return getSelectors(parsed);
}
function getSelectors(parsed) {
if (parsed[0] == ",") {
return parsed.slice(1);
}
return [parsed];
}
function matchesAny(sels, context) {
for (var i = 0; i < sels.length; i++) {
if (matches(sels[i], context)) {
return true;
}
}
return false;
}
function matches(sel, context) {
var path = context.parents.concat([context]),
i = path.length - 1,
j = sel.length - 1;
// walk up the ancestors
var must = true;
while(parts.length && path.length) {
var part = parts[0],
key = path[0];
while(j >= 0 && i >= 0) {
var part = sel[j],
context = path[i];
if (part == ">") {
parts.shift();
j--;
must = true;

@@ -52,4 +70,4 @@ continue;

if (matchesKey(part, key)) {
parts.shift();
if (matchesKey(part, context)) {
j--;
}

@@ -60,26 +78,86 @@ else if(must) {

path.shift();
i--;
must = false;
}
return parts.length == 0;
return j == -1;
}
function matchesKey(part, key) {
if (part.id && part.id != key) {
function matchesKey(part, context) {
var key = context.key,
node = context.node,
parent = context.parent;
if (part.id && key != part.id) {
return false;
}
if (part.type) {
if (part.type == "null") {
if (context.node !== null) {
return false;
}
}
else if (part.type == "array") {
if (!isArray(context.node)) {
return false;
}
}
else if (part.type == "object") {
if (typeof context.node != "object"
|| context.node === null || isArray(context.node)) {
return false;
}
}
else if (part.type != typeof context.node) {
return false;
}
}
if (part.pf == ":nth-child") {
if (part.a == 0
&& (parseInt(key) + 1) !== part.b) {
var index = parseInt(key) + 1;
if ((part.a == 0 && index !== part.b) // :nth-child(i)
|| (part.a == 1 && !(index >= -part.b)) // :nth-child(n)
|| (part.a == -1 && !(index <= part.b)) // :nth-child(-n + 1)
|| (part.a == 2 && index % 2 != part.b)) { // :nth-child(even)
return false;
}
else if (part.a == 2
&& (parseInt(key) % 2) != part.b) {
return false ;
}
if (part.pf == ":nth-last-child") {
var n = context.parent && context.parent.node.length;
if (!n || key != n - part.b) {
return false;
}
}
if (part.pc == ":root" && key != "") {
if (part.pc == ":only-child") {
var n = context.parent && context.parent.node.length;
if (!n || n != 1) {
return false;
}
}
if (part.pc == ":root" && key !== undefined) {
return false;
}
if (part.has) {
var sels = getSelectors(part.has[0]),
match = false;
traverse(node).forEach(function(child) {
if (matchesAny(sels, this)) {
match = true;
}
});
if (!match) {
return false;
}
}
if (part.expr) {
var expr = part.expr, lhs = expr[0], op = expr[1], rhs = expr[2];
if (typeof node != "string"
|| (!lhs && op == "=" && node != rhs) // :val("str")
|| (!lhs && op == "*=" && node.indexOf(rhs) == -1)) { // :contains("substr")
return false;
}
}
return true;
}
var isArray = Array.isArray || function(obj) {
return toString.call(obj) === '[object Array]';
}
{
"name": "js-select",
"description": "Traverse and modify objects with JSONSelect selectors",
"version": "0.2.0",
"version": "0.4.0",
"author": "Heather Arthur <fayearthur@gmail.com>",

@@ -16,4 +16,6 @@ "repository": {

"devDependencies": {
"nomnom": "0.6.x",
"color": "0.3.x"
},
"keywords": ["json"]
}

@@ -6,4 +6,2 @@ # js-select

```javascript
var select = require("js-select");
var people = {

@@ -32,3 +30,3 @@ george: {

if (this.matches(".mary > .movie")) {
this.update(node.toLowerCase());
this.remove();
}

@@ -40,19 +38,29 @@ }

js-select supports the following [JSONSelect](http://jsonselect.org/) selectors so far:
js-select supports the following [JSONSelect](http://jsonselect.org/) selectors:
```
"*"
".key"
".ancestor .key"
".parent > .key"
":root"
":nth-child(n)"
":nth-child(even)"
":nth-child(odd)"
":first-child"
*
type
.key
.ancestor .key
.parent > .key
.sibling ~ .key
:root
:nth-child(n)
:nth-child(even)
:nth-child(odd)
:nth-last-child(n)
:first-child
:last-child
:only-child
:has(selector)
:val("string")
:contains("substring")
```
See [details](http://jsonselect.org/#docs/overview) on each selector, and [try them](http://jsonselect.org/#tryit) out on the JSONSelect website.
# install
Download the code, then with [npm](http://npmjs.org):
For [node](http://nodejs.org), install with [npm](http://npmjs.org):

@@ -63,2 +71,14 @@ ```bash

Get a browser file after npm-installing using [browserify](https://github.com/substack/node-browserify)
For the browser, download the select.js file or fetch the latest version from [npm](http://npmjs.org) and build a browser file using [browserify](https://github.com/substack/node-browserify):
```bash
npm install browserify -g
npm install js-select
browserify --require js-select --outfile select.js
```
this will build a browser file with `require('js-select')` available.
# propers
Huge thanks to [@substack](http://github.com/substack) for the ingenious [js-traverse](https://github.com/substack/js-traverse) and [@lloyd](https://github.com/lloyd) for the ingenious [JSONSelect spec](http://http://jsonselect.org/) and [selector parser](http://search.npmjs.org/#/JSONSelect).

@@ -1,2 +0,4 @@

var select = require("./index");
var select = require("./index"),
JSONSelect = require("JSONSelect"),
traverse = require("traverse");

@@ -6,5 +8,5 @@ var people = {

age: 15,
movies: [{
movies: [{
name: "Twilight",
stars: 3
stars: false
},

@@ -14,5 +16,11 @@ { name: "Clueless",

}]
},
"george": {
lang: "eng",
stars: 6
}
};
console.log(select(people, ":root").nodes())
var selector = ':contains("Clueless")';
console.log(select(people, selector).nodes())
console.log(JSONSelect.match(selector, people))

@@ -28,7 +28,10 @@ var assert = require("assert"),

}]
},
"chris" : {
car: null,
male: true
}
}
var people2 = traverse.clone(people);
assert.deepEqual(select(people, "*").nodes(), [{"george":{"age":35,"movies":[{"name":"Repo Man","stars":5}]},"mary":{"age":15,"movies":[{"name":"Twilight","stars":3},{"name":"Trudy","stars":2},{"name":"The Fighter","stars":4}]}},{"age":35,"movies":[{"name":"Repo Man","stars":5}]},35,[{"name":"Repo Man","stars":5}],{"name":"Repo Man","stars":5},"Repo Man",5,{"age":15,"movies":[{"name":"Twilight","stars":3},{"name":"Trudy","stars":2},{"name":"The Fighter","stars":4}]},15,[{"name":"Twilight","stars":3},{"name":"Trudy","stars":2},{"name":"The Fighter","stars":4}],{"name":"Twilight","stars":3},"Twilight",3,{"name":"Trudy","stars":2},"Trudy",2,{"name":"The Fighter","stars":4},"The Fighter",4]);
assert.deepEqual(select(people, "*").nodes(), [{"george":{"age":35,"movies":[{"name":"Repo Man","stars":5}]},"mary":{"age":15,"movies":[{"name":"Twilight","stars":3},{"name":"Trudy","stars":2},{"name":"The Fighter","stars":4}]},"chris":{"car":null,"male":true}},{"age":35,"movies":[{"name":"Repo Man","stars":5}]},35,[{"name":"Repo Man","stars":5}],{"name":"Repo Man","stars":5},"Repo Man",5,{"age":15,"movies":[{"name":"Twilight","stars":3},{"name":"Trudy","stars":2},{"name":"The Fighter","stars":4}]},15,[{"name":"Twilight","stars":3},{"name":"Trudy","stars":2},{"name":"The Fighter","stars":4}],{"name":"Twilight","stars":3},"Twilight",3,{"name":"Trudy","stars":2},"Trudy",2,{"name":"The Fighter","stars":4},"The Fighter",4,{"car":null,"male":true},null,true]);
assert.deepEqual(select(people, ".george").nodes(), [{"age":35,"movies":[{"name":"Repo Man","stars":5}]}]);

@@ -42,8 +45,37 @@ assert.deepEqual(select(people, ".george .age").nodes(), [35]);

assert.deepEqual(select(people, ":first-child").nodes(), [{"name":"Repo Man","stars":5},{"name":"Twilight","stars":3}]);
assert.deepEqual(select(people, ":nth-child(1)").nodes(), select(people, ":first-child").nodes());
assert.deepEqual(select(people, ":nth-child(2)").nodes(), [{"name":"Trudy","stars":2}]);
assert.deepEqual(select(people, ":nth-child(even)").nodes(), [{"name":"Repo Man","stars":5},{"name":"Twilight","stars":3},{"name":"The Fighter","stars":4}]);
assert.deepEqual(select(people, ":nth-child(odd)").nodes(), [{"name":"Trudy","stars":2}]);
assert.deepEqual(select(people, ":root").nodes(), [{"george":{"age":35,"movies":[{"name":"Repo Man","stars":5}]},"mary":{"age":15,"movies":[{"name":"Twilight","stars":3},{"name":"Trudy","stars":2},{"name":"The Fighter","stars":4}]}}]);
assert.deepEqual(select(people, ":nth-child(odd)").nodes(), [{"name":"Repo Man","stars":5},{"name":"Twilight","stars":3},{"name":"The Fighter","stars":4}]);
assert.deepEqual(select(people, ":nth-child(even)").nodes(), [{"name":"Trudy","stars":2}]);
assert.deepEqual(select(people, ":nth-child(-n+1)").nodes(), select(people, ":first-child").nodes());
assert.deepEqual(select(people, ":nth-child(-n+2)").nodes(), [{"name":"Repo Man","stars":5},{"name":"Twilight","stars":3},{"name":"Trudy","stars":2}]);
assert.deepEqual(select(people, ":nth-child(n)").nodes(), [{"name":"Repo Man","stars":5},{"name":"Twilight","stars":3},{"name":"Trudy","stars":2},{"name":"The Fighter","stars":4}]);
assert.deepEqual(select(people, ":nth-child(n-1)").nodes(), select(people, ":nth-child(n)").nodes());
assert.deepEqual(select(people, ":nth-child(n-2)").nodes(), [{"name":"Trudy","stars":2},{"name":"The Fighter","stars":4}]);
assert.deepEqual(select(people, ":last-child").nodes(), [{"name":"Repo Man","stars":5},{"name":"The Fighter","stars":4}]);
assert.deepEqual(select(people, ":nth-last-child(1)").nodes(), select(people, ":last-child").nodes());
assert.deepEqual(select(people, ":nth-last-child(2)").nodes(), [{"name":"Trudy","stars":2}]);
assert.deepEqual(select(people, ":only-child").nodes(), [{"name":"Repo Man","stars":5}]);
assert.deepEqual(select(people, ":root").nodes(),[{"george":{"age":35,"movies":[{"name":"Repo Man","stars":5}]},"mary":{"age":15,"movies":[{"name":"Twilight","stars":3},{"name":"Trudy","stars":2},{"name":"The Fighter","stars":4}]},"chris":{"car":null,"male":true}}])
assert.deepEqual(select(people, "string").nodes(),["Repo Man","Twilight","Trudy","The Fighter"]);
assert.deepEqual(select(people, "number").nodes(),[35,5,15,3,2,4]);
assert.deepEqual(select(people, "boolean").nodes(),[true]);
assert.deepEqual(select(people, "object").nodes(),[{"george":{"age":35,"movies":[{"name":"Repo Man","stars":5}]},"mary":{"age":15,"movies":[{"name":"Twilight","stars":3},{"name":"Trudy","stars":2},{"name":"The Fighter","stars":4}]},"chris":{"car":null,"male":true}},{"age":35,"movies":[{"name":"Repo Man","stars":5}]},{"name":"Repo Man","stars":5},{"age":15,"movies":[{"name":"Twilight","stars":3},{"name":"Trudy","stars":2},{"name":"The Fighter","stars":4}]},{"name":"Twilight","stars":3},{"name":"Trudy","stars":2},{"name":"The Fighter","stars":4},{"car":null,"male":true}]);
assert.deepEqual(select(people, "array").nodes(),[[{"name":"Repo Man","stars":5}],[{"name":"Twilight","stars":3},{"name":"Trudy","stars":2},{"name":"The Fighter","stars":4}]]);
assert.deepEqual(select(people, "null").nodes(),[null]);
assert.deepEqual(select(people, "number, string, boolean").nodes(), [35,"Repo Man",5,15,"Twilight",3,"Trudy",2,"The Fighter",4,true])
assert.deepEqual(select(people, ":has(.car) > .male").nodes(), [true]);
assert.deepEqual(select(people, ".male ~ .car").nodes(), [null])
assert.deepEqual(select(people, ':val("Twilight")').nodes(), ["Twilight"])
assert.deepEqual(select(people, ':val("Twi")').nodes(), [])
assert.deepEqual(select(people, ':contains("Twi")').nodes(), ["Twilight"])
assert.deepEqual(select(people, ':contains("weif")').nodes(), [])
// invalid

@@ -74,6 +106,20 @@ assert.deepEqual(select(people, ".hmmm").nodes(), []);

console.time("big")
assert.deepEqual(select(timeline, ".bug .id").nodes().length, 126);
assert.deepEqual(select(timeline, ".id").nodes().length, 141);
assert.deepEqual(select(timeline, ".comments .id").nodes().length, 115);
console.timeEnd("big")
console.time("select time");
assert.equal(select(timeline, ".bug .id").nodes().length, 126);
assert.equal(select(timeline, ".id").nodes().length, 141);
assert.equal(select(timeline, ".comments .id").nodes().length, 115);
assert.equal(select(timeline, ":nth-child(n-2)").nodes().length, 335);
assert.equal(select(timeline, "object").nodes().length, 927);
assert.equal(select(timeline, "*").nodes().length, 3281);
console.timeEnd("select time")
var sel = require("JSONSelect");
console.time("JSONSelect time")
assert.equal(sel.match(".bug .id", timeline).length, 126);
assert.equal(sel.match(".id", timeline).length, 141);
assert.equal(sel.match(".comments .id", timeline).length, 115);
assert.equal(sel.match(":nth-child(n-2)", timeline).length, 335);
assert.equal(sel.match("object", timeline).length, 927);
assert.equal(sel.match("*", timeline).length, 3281);
console.timeEnd("JSONSelect time")
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc