summaryrefslogtreecommitdiff
path: root/source/bower_components/modernizr/test/js/lib/jsonselect.js
diff options
context:
space:
mode:
Diffstat (limited to 'source/bower_components/modernizr/test/js/lib/jsonselect.js')
-rw-r--r--source/bower_components/modernizr/test/js/lib/jsonselect.js279
1 files changed, 279 insertions, 0 deletions
diff --git a/source/bower_components/modernizr/test/js/lib/jsonselect.js b/source/bower_components/modernizr/test/js/lib/jsonselect.js
new file mode 100644
index 0000000..84913d0
--- /dev/null
+++ b/source/bower_components/modernizr/test/js/lib/jsonselect.js
@@ -0,0 +1,279 @@
+/*! Copyright (c) 2011, Lloyd Hilaiel, ISC License */
+/*
+ * This is the JSONSelect reference implementation, in javascript.
+ */
+(function(exports) {
+
+ var // localize references
+ toString = Object.prototype.toString;
+
+ function jsonParse(str) {
+ try {
+ if(JSON && JSON.parse){
+ return JSON.parse(str);
+ }
+ return (new Function("return " + str))();
+ } catch(e) {
+ te("ijs");
+ }
+ }
+
+ // emitted error codes.
+ var errorCodes = {
+ "ijs": "invalid json string",
+ "mpc": "multiple pseudo classes (:xxx) not allowed",
+ "mepf": "malformed expression in pseudo-function",
+ "nmi": "multiple ids not allowed",
+ "se": "selector expected",
+ "sra": "string required after '.'",
+ "uc": "unrecognized char",
+ "ujs": "unclosed json string",
+ "upc": "unrecognized pseudo class"
+ };
+
+ // throw an error message
+ function te(ec) {
+ throw new Error(errorCodes[ec]);
+ }
+
+ // THE LEXER
+ var toks = {
+ psc: 1, // pseudo class
+ psf: 2, // pseudo class function
+ typ: 3, // type
+ str: 4 // string
+ };
+
+ var pat = /^(?:([\r\n\t\ ]+)|([*.,>])|(string|boolean|null|array|object|number)|(:(?:root|first-child|last-child|only-child))|(:(?:nth-child|nth-last-child))|(:\w+)|(\"(?:[^\\]|\\[^\"])*\")|(\")|((?:[_a-zA-Z]|[^\0-\0177]|\\[^\r\n\f0-9a-fA-F])(?:[_a-zA-Z0-9\-]|[^\u0000-\u0177]|(?:\\[^\r\n\f0-9a-fA-F]))*))/;
+ var exprPat = /^\s*\(\s*(?:([+\-]?)([0-9]*)n\s*(?:([+\-])\s*([0-9]))?|(odd|even)|([+\-]?[0-9]+))\s*\)/;
+ var lex = function (str, off) {
+ if (!off) off = 0;
+ var m = pat.exec(str.substr(off));
+ if (!m) return undefined;
+ off+=m[0].length;
+ var a;
+ if (m[1]) a = [off, " "];
+ else if (m[2]) a = [off, m[0]];
+ else if (m[3]) a = [off, toks.typ, m[0]];
+ else if (m[4]) a = [off, toks.psc, m[0]];
+ else if (m[5]) a = [off, toks.psf, m[0]];
+ else if (m[6]) te("upc");
+ else if (m[7]) a = [off, toks.str, jsonParse(m[0])];
+ else if (m[8]) te("ujs");
+ else if (m[9]) a = [off, toks.str, m[0].replace(/\\([^\r\n\f0-9a-fA-F])/g,"$1")];
+ return a;
+ };
+
+ // THE PARSER
+
+ var parse = function (str) {
+ var a = [], off = 0, am;
+
+ while (true) {
+ var s = parse_selector(str, off);
+ a.push(s[1]);
+ s = lex(str, off = s[0]);
+ if (s && s[1] === " ") s = lex(str, off = s[0]);
+ if (!s) break;
+ // now we've parsed a selector, and have something else...
+ if (s[1] === ">") {
+ a.push(">");
+ off = s[0];
+ } else if (s[1] === ",") {
+ if (am === undefined) am = [ ",", a ];
+ else am.push(a);
+ a = [];
+ off = s[0];
+ }
+ }
+ if (am) am.push(a);
+ return am ? am : a;
+ };
+
+ var parse_selector = function(str, off) {
+ var soff = off;
+ var s = { };
+ var l = lex(str, off);
+ // skip space
+ if (l && l[1] === " ") { soff = off = l[0]; l = lex(str, off); }
+ if (l && l[1] === toks.typ) {
+ s.type = l[2];
+ l = lex(str, (off = l[0]));
+ } else if (l && l[1] === "*") {
+ // don't bother representing the universal sel, '*' in the
+ // parse tree, cause it's the default
+ l = lex(str, (off = l[0]));
+ }
+
+ // now support either an id or a pc
+ while (true) {
+ if (l === undefined) {
+ break;
+ } else if (l[1] === ".") {
+ l = lex(str, (off = l[0]));
+ if (!l || l[1] !== toks.str) te("sra");
+ if (s.id) te("nmi");
+ s.id = l[2];
+ } else if (l[1] === toks.psc) {
+ if (s.pc || s.pf) te("mpc");
+ // collapse first-child and last-child into nth-child expressions
+ if (l[2] === ":first-child") {
+ s.pf = ":nth-child";
+ s.a = 0;
+ s.b = 1;
+ } else if (l[2] === ":last-child") {
+ s.pf = ":nth-last-child";
+ s.a = 0;
+ s.b = 1;
+ } else {
+ s.pc = l[2];
+ }
+ } else if (l[1] === toks.psf) {
+ if (s.pc || s.pf ) te("mpc");
+ s.pf = l[2];
+ var m = exprPat.exec(str.substr(l[0]));
+ if (!m) te("mepf");
+ if (m[5]) {
+ s.a = 2;
+ s.b = (m[5] === "odd") ? 1 : 0;
+ } else if (m[6]) {
+ s.a = 0;
+ s.b = parseInt(m[6], 10);
+ } else {
+ s.a = parseInt((m[1] ? m[1] : "+") + (m[2] ? m[2] : "1"),10);
+ s.b = m[3] ? parseInt(m[3] + m[4],10) : 0;
+ }
+ l[0] += m[0].length;
+ } else {
+ break;
+ }
+ l = lex(str, (off = l[0]));
+ }
+
+ // now if we didn't actually parse anything it's an error
+ if (soff === off) te("se");
+
+ return [off, s];
+ };
+
+ // THE EVALUATOR
+
+ function isArray(o) {
+ return Array.isArray ? Array.isArray(o) :
+ toString.call(o) === "[object Array]";
+ }
+
+ function mytypeof(o) {
+ if (o === null) return "null";
+ var to = typeof o;
+ if (to === "object" && isArray(o)) to = "array";
+ return to;
+ }
+
+ function mn(node, sel, id, num, tot) {
+ var sels = [];
+ var cs = (sel[0] === ">") ? sel[1] : sel[0];
+ var m = true, mod;
+ if (cs.type) m = m && (cs.type === mytypeof(node));
+ if (cs.id) m = m && (cs.id === id);
+ if (m && cs.pf) {
+ if (cs.pf === ":nth-last-child") num = tot - num;
+ else num++;
+ if (cs.a === 0) {
+ m = cs.b === num;
+ } else {
+ mod = ((num - cs.b) % cs.a);
+
+ m = (!mod && ((num*cs.a + cs.b) >= 0));
+ }
+ }
+
+ // should we repeat this selector for descendants?
+ if (sel[0] !== ">" && sel[0].pc !== ":root") sels.push(sel);
+
+ if (m) {
+ // is there a fragment that we should pass down?
+ if (sel[0] === ">") { if (sel.length > 2) { m = false; sels.push(sel.slice(2)); } }
+ else if (sel.length > 1) { m = false; sels.push(sel.slice(1)); }
+ }
+
+ return [m, sels];
+ }
+
+ function forEach(sel, obj, fun, id, num, tot) {
+ var a = (sel[0] === ",") ? sel.slice(1) : [sel],
+ a0 = [],
+ call = false,
+ i = 0, j = 0, l = 0, k, x;
+ for (i = 0; i < a.length; i++) {
+ x = mn(obj, a[i], id, num, tot);
+ if (x[0]) {
+ call = true;
+ }
+ for (j = 0; j < x[1].length; j++) {
+ a0.push(x[1][j]);
+ }
+ }
+ if (a0.length && typeof obj === "object") {
+ if (a0.length >= 1) {
+ a0.unshift(",");
+ }
+ if (isArray(obj)) {
+ for (i = 0; i < obj.length; i++) {
+ forEach(a0, obj[i], fun, undefined, i, obj.length);
+ }
+ } else {
+ // it's a shame to do this for :last-child and other
+ // properties which count from the end when we don't
+ // even know if they're present. Also, the stream
+ // parser is going to be pissed.
+ l = 0;
+ for (k in obj) {
+ if (obj.hasOwnProperty(k)) {
+ l++;
+ }
+ }
+ i = 0;
+ for (k in obj) {
+ if (obj.hasOwnProperty(k)) {
+ forEach(a0, obj[k], fun, k, i++, l);
+ }
+ }
+ }
+ }
+ if (call && fun) {
+ fun(obj);
+ }
+ }
+
+ function match(sel, obj) {
+ var a = [];
+ forEach(sel, obj, function(x) {
+ a.push(x);
+ });
+ return a;
+ }
+
+ function compile(sel) {
+ return {
+ sel: parse(sel),
+ match: function(obj){
+ return match(this.sel, obj);
+ },
+ forEach: function(obj, fun) {
+ return forEach(this.sel, obj, fun);
+ }
+ };
+ }
+
+ exports._lex = lex;
+ exports._parse = parse;
+ exports.match = function (sel, obj) {
+ return compile(sel).match(obj);
+ };
+ exports.forEach = function(sel, obj, fun) {
+ return compile(sel).forEach(obj, fun);
+ };
+ exports.compile = compile;
+})(typeof exports === "undefined" ? (window.JSONSelect = {}) : exports);
+