lib/terminus/public/pathology.js in terminus-0.4.0 vs lib/terminus/public/pathology.js in terminus-0.5.0

- old
+ new

@@ -3,24 +3,24 @@ result = result || new Pathology.XPathResult(resultType); var expression = Pathology.XPathParser.parse(xpathExpression); expression.evaluate(context, context, resultType, result); return result; }, - + atomize: function(expression, context, root) { var result = expression.evaluate(context, root); if (result && result.atomize) result = result.atomize(); return result; }, - + array: function(list) { if (!list) return []; var array = [], i = list.length; while (i--) array[i] = list[i]; return array; }, - + indexOf: function(list, item) { if (list.indexOf) return list.indexOf(item); for (var i = 0, n = list.length; i < n; i++) { if (list[i] === item) return i; } @@ -83,21 +83,21 @@ }; Pathology.XPathResult.prototype.makeString = function() { var first = this._nodes[0]; if (!first) return ''; - + switch (first.nodeType) { case XPathResult.STRING_TYPE: return this.atomize(); - + case XPathResult.BOOLEAN_TYPE: var parts = []; for (var i = 0, n = this._nodes.length; i < n; i++) parts.push(this._nodes[i].nodeValue); return parts.join(''); - + default: var result = document.evaluate('//text()', first, null, XPathResult.ANY_TYPE, null); return result.makeString(); } }; @@ -110,47 +110,47 @@ if (destination[key] !== source[key]) destination[key] = source[key]; } return destination; }; - + var find = function (root, objectName) { var parts = objectName.split('.'), part; - + while (part = parts.shift()) { root = root[part]; if (root === undefined) throw new Error('Cannot find object named ' + objectName); } return root; }; - + var formatError = function (error) { var lines = error.input.split(/\n/g), lineNo = 0, offset = 0; - + while (offset < error.offset + 1) { offset += lines[lineNo].length + 1; lineNo += 1; } var message = 'Line ' + lineNo + ': expected ' + error.expected + '\n', line = lines[lineNo - 1]; - + message += line + '\n'; offset -= line.length + 1; - + while (offset < error.offset) { message += ' '; offset += 1; } return message + '^'; }; - + var Grammar = { - __consume__union_expression: function(input) { + __consume__union_expression: function() { var address0 = null, index0 = this._offset; this._nodeCache["union_expression"] = this._nodeCache["union_expression"] || {}; var cached = this._nodeCache["union_expression"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -285,11 +285,11 @@ } else { address0 = null; } return this._nodeCache["union_expression"][index0] = address0; }, - __consume__location_path: function(input) { + __consume__location_path: function() { var address0 = null, index0 = this._offset; this._nodeCache["location_path"] = this._nodeCache["location_path"] || {}; var cached = this._nodeCache["location_path"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -348,11 +348,11 @@ } else { address0 = null; } return this._nodeCache["location_path"][index0] = address0; }, - __consume__location_step: function(input) { + __consume__location_step: function() { var address0 = null, index0 = this._offset; this._nodeCache["location_step"] = this._nodeCache["location_step"] || {}; var cached = this._nodeCache["location_step"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -555,11 +555,11 @@ } else { address0 = null; } return this._nodeCache["location_step"][index0] = address0; }, - __consume__axis: function(input) { + __consume__axis: function() { var address0 = null, index0 = this._offset; this._nodeCache["axis"] = this._nodeCache["axis"] || {}; var cached = this._nodeCache["axis"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -677,11 +677,11 @@ this._offset = index1; } } return this._nodeCache["axis"][index0] = address0; }, - __consume__axis_shorthand: function(input) { + __consume__axis_shorthand: function() { var address0 = null, index0 = this._offset; this._nodeCache["axis_shorthand"] = this._nodeCache["axis_shorthand"] || {}; var cached = this._nodeCache["axis_shorthand"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -808,11 +808,11 @@ } } } return this._nodeCache["axis_shorthand"][index0] = address0; }, - __consume__node_test: function(input) { + __consume__node_test: function() { var address0 = null, index0 = this._offset; this._nodeCache["node_test"] = this._nodeCache["node_test"] || {}; var cached = this._nodeCache["node_test"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -902,11 +902,11 @@ } else { address0 = null; } return this._nodeCache["node_test"][index0] = address0; }, - __consume__node_condition: function(input) { + __consume__node_condition: function() { var address0 = null, index0 = this._offset; this._nodeCache["node_condition"] = this._nodeCache["node_condition"] || {}; var cached = this._nodeCache["node_condition"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -1014,11 +1014,11 @@ } else { address0 = null; } return this._nodeCache["node_condition"][index0] = address0; }, - __consume__node_name: function(input) { + __consume__node_name: function() { var address0 = null, index0 = this._offset; this._nodeCache["node_name"] = this._nodeCache["node_name"] || {}; var cached = this._nodeCache["node_name"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -1070,11 +1070,11 @@ } else { address0 = null; } return this._nodeCache["node_name"][index0] = address0; }, - __consume__subscript: function(input) { + __consume__subscript: function() { var address0 = null, index0 = this._offset; this._nodeCache["subscript"] = this._nodeCache["subscript"] || {}; var cached = this._nodeCache["subscript"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -1191,11 +1191,11 @@ } else { address0 = null; } return this._nodeCache["subscript"][index0] = address0; }, - __consume__node_predicate: function(input) { + __consume__node_predicate: function() { var address0 = null, index0 = this._offset; this._nodeCache["node_predicate"] = this._nodeCache["node_predicate"] || {}; var cached = this._nodeCache["node_predicate"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -1314,11 +1314,11 @@ } else { address0 = null; } return this._nodeCache["node_predicate"][index0] = address0; }, - __consume__expression: function(input) { + __consume__expression: function() { var address0 = null, index0 = this._offset; this._nodeCache["expression"] = this._nodeCache["expression"] || {}; var cached = this._nodeCache["expression"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -1345,11 +1345,11 @@ } } } return this._nodeCache["expression"][index0] = address0; }, - __consume__or_expression: function(input) { + __consume__or_expression: function() { var address0 = null, index0 = this._offset; this._nodeCache["or_expression"] = this._nodeCache["or_expression"] || {}; var cached = this._nodeCache["or_expression"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -1432,11 +1432,11 @@ this._offset = index1; } } return this._nodeCache["or_expression"][index0] = address0; }, - __consume__and_expression: function(input) { + __consume__and_expression: function() { var address0 = null, index0 = this._offset; this._nodeCache["and_expression"] = this._nodeCache["and_expression"] || {}; var cached = this._nodeCache["and_expression"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -1519,11 +1519,11 @@ this._offset = index1; } } return this._nodeCache["and_expression"][index0] = address0; }, - __consume__comparison: function(input) { + __consume__comparison: function() { var address0 = null, index0 = this._offset; this._nodeCache["comparison"] = this._nodeCache["comparison"] || {}; var cached = this._nodeCache["comparison"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -1582,11 +1582,11 @@ this._offset = index1; } } return this._nodeCache["comparison"][index0] = address0; }, - __consume__comparator: function(input) { + __consume__comparator: function() { var address0 = null, index0 = this._offset; this._nodeCache["comparator"] = this._nodeCache["comparator"] || {}; var cached = this._nodeCache["comparator"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -1653,11 +1653,11 @@ this._offset = index1; } } return this._nodeCache["comparator"][index0] = address0; }, - __consume__atom: function(input) { + __consume__atom: function() { var address0 = null, index0 = this._offset; this._nodeCache["atom"] = this._nodeCache["atom"] || {}; var cached = this._nodeCache["atom"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -1806,11 +1806,11 @@ } else { address0 = null; } return this._nodeCache["atom"][index0] = address0; }, - __consume__value: function(input) { + __consume__value: function() { var address0 = null, index0 = this._offset; this._nodeCache["value"] = this._nodeCache["value"] || {}; var cached = this._nodeCache["value"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -1832,11 +1832,11 @@ } } } return this._nodeCache["value"][index0] = address0; }, - __consume__function_call: function(input) { + __consume__function_call: function() { var address0 = null, index0 = this._offset; this._nodeCache["function_call"] = this._nodeCache["function_call"] || {}; var cached = this._nodeCache["function_call"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -1943,11 +1943,11 @@ } else { address0 = null; } return this._nodeCache["function_call"][index0] = address0; }, - __consume__function_name: function(input) { + __consume__function_name: function() { var address0 = null, index0 = this._offset; this._nodeCache["function_name"] = this._nodeCache["function_name"] || {}; var cached = this._nodeCache["function_name"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -1999,11 +1999,11 @@ } else { address0 = null; } return this._nodeCache["function_name"][index0] = address0; }, - __consume__function_args: function(input) { + __consume__function_args: function() { var address0 = null, index0 = this._offset; this._nodeCache["function_args"] = this._nodeCache["function_args"] || {}; var cached = this._nodeCache["function_args"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -2130,11 +2130,11 @@ } this._offset += 0; } return this._nodeCache["function_args"][index0] = address0; }, - __consume__integer: function(input) { + __consume__integer: function() { var address0 = null, index0 = this._offset; this._nodeCache["integer"] = this._nodeCache["integer"] || {}; var cached = this._nodeCache["integer"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -2241,11 +2241,11 @@ } else { address0 = null; } return this._nodeCache["integer"][index0] = address0; }, - __consume__string: function(input) { + __consume__string: function() { var address0 = null, index0 = this._offset; this._nodeCache["string"] = this._nodeCache["string"] || {}; var cached = this._nodeCache["string"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -2720,11 +2720,11 @@ this._offset = index1; } } return this._nodeCache["string"][index0] = address0; }, - __consume__space: function(input) { + __consume__space: function() { var address0 = null, index0 = this._offset; this._nodeCache["space"] = this._nodeCache["space"] || {}; var cached = this._nodeCache["space"][index0]; if (cached) { this._offset += cached.textValue.length; @@ -2777,17 +2777,17 @@ address0 = null; } return this._nodeCache["space"][index0] = address0; } }; - + var Parser = function(input) { this._input = input; this._offset = 0; this._nodeCache = {}; }; - + Parser.prototype.parse = function() { var result = this.__consume__union_expression(); if (result && this._offset === this._input.length) { return result; } @@ -2796,39 +2796,39 @@ } var message = formatError(this.error); var error = new Error(message); throw error; }; - + Parser.parse = function(input) { var parser = new Parser(input); return parser.parse(); }; - + extend(Parser.prototype, Grammar); - + var SyntaxNode = function(textValue, offset, elements, properties) { this.textValue = textValue; this.offset = offset; this.elements = elements || []; if (!properties) return; for (var key in properties) this[key] = properties[key]; }; - + SyntaxNode.prototype.forEach = function(block, context) { for (var i = 0, n = this.elements.length; i < n; i++) { block.call(context, this.elements[i], i); } }; - + Parser.SyntaxNode = SyntaxNode; - + if (typeof require === "function" && typeof exports === "object") { exports.Grammar = Grammar; exports.Parser = Parser; exports.parse = Parser.parse; - + if (typeof Pathology !== "undefined") { Pathology.XPath = Grammar; Pathology.XPathParser = Parser; Pathology.XPathParser.formatError = formatError; } @@ -2864,55 +2864,55 @@ Pathology.Axis.prototype.walk = function(context, block, scope) { var children = context.childNodes, attributes = Pathology.array(context.attributes), sibling; - + if (context.checked) attributes.push({ nodeName: 'checked', nodeValue: true, nodeType: XPathResult.STRING_TYPE }); - + if (context.selected) attributes.push({ nodeName: 'selected', nodeValue: true, nodeType: XPathResult.STRING_TYPE }); - + switch (this.name) { case 'attribute': for (var i = 0, n = attributes.length; i < n; i++) { block.call(scope, attributes[i]); } break; - + case 'child': for (var i = 0, n = children.length; i < n; i++) { block.call(scope, children[i]); } break; - + case 'descendant-or-self': block.call(scope, context); for (var i = 0, n = children.length; i < n; i++) { this.walk(children[i], block, scope); } break; - + case 'following-sibling': sibling = context.nextSibling; while (sibling) { block.call(scope, sibling); sibling = sibling.nextSibling; } break; - + case 'parent': block.call(scope, context.parentNode); break; - + case 'self': block.call(scope, context); break; } }; @@ -2922,16 +2922,16 @@ '..': 'parent', '.' : 'self', '/' : 'descendant-or-self', '' : 'child' }; - + Pathology.Axis.fromAST = function(node) { var name = node.axis_name ? node.axis_name.textValue : node.textValue; - + return new this(this.SHORTHANDS[name] || name); }; Pathology.XPathParser.Comparison = { @@ -2941,22 +2941,22 @@ left = this.left.evaluate(context, root), right = Pathology.atomize(this.right, context, root), viable = false, array = (right instanceof Array), node; - + if (left._nodes) { for (var i = 0, n = left._nodes.length; i < n; i++) { node = left._nodes[i]; if (comparator === '=') { viable = viable || (array ? Pathology.indexOf(right, node.nodeValue) >= 0 : (node.nodeValue === right || node.innerHTML === right)); } else if (comparator === '!=') { viable = viable || (array ? Pathology.indexOf(right, node.nodeValue) < 0 : (node.nodeValue !== right && node.innerHTML !== right)); } } return viable; - + } else { switch (comparator) { case '=': return array ? Pathology.indexOf(right, left.nodeValue) >= 0 : left == right; case '!=': return array ? Pathology.indexOf(right, node.nodeValue) < 0 : left != right; } @@ -2967,65 +2967,65 @@ Pathology.XPathParser.FunctionCall = { getArguments: function(context, root) { var args = [], rest = this.function_args.rest; - + if (this.function_args.first && this.function_args.first.evaluate) { args.push(this.function_args.first.evaluate(context, root)); } if (rest) { for (var i = 0, n = rest.elements.length; i < n; i++) args.push(rest.elements[i].expression.evaluate(context, root)); } return args; }, - + evaluate: function(context, root) { var args = this.getArguments(context, root), proc = this.REGISTER[this.function_name.textValue]; - + return proc.apply(context, args); }, - + REGISTER: { 'concat': function() { var string = ''; for (var i = 0, n = arguments.length; i < n; i++) string += arguments[i].makeString ? arguments[i].makeString() : arguments[i]; return string; }, - + 'contains': function(haystack, needle) { if (!haystack) return false; if (haystack.makeString) haystack = haystack.makeString(); - + return haystack.toString().indexOf(needle) >= 0; }, - + 'normalize-space': function(string) { if (string.makeString) string = string.makeString(); - + return string.toString().replace(/^\s*/g, '') .replace(/\s*$/g, '') .replace(/\s+/g, ' '); }, - + 'name': function() { return this.nodeName.toLowerCase(); }, - + 'not': function(value) { if (value && value.atomize) value = value.atomize(); if (typeof value === 'string') return false; return !value; }, - + 'string': function(value) { return value.atomize().innerText; }, - + 'text': function() { return document.evaluate('/text()', this, null, XPathResult.ANY_TYPE, null); } } }; @@ -3035,51 +3035,51 @@ eachStep: function(block, scope) { var list = [this.head].concat(this.rest.elements); for (var i = 0, n = list.length; i < n; i++) block.call(scope, list[i]); }, - + evaluate: function(context, root, resultType, result) { result = result || new Pathology.XPathResult(XPathResult.ANY_TYPE); resultType = resultType || XPathResult.ANY_TYPE; - + var intermediate = new Pathology.XPathResult(resultType), startNode = this.head.isRelative() ? context : root, steps = [this.head].concat(this.rest.elements), step, nextStage, i, j, n, m; - + intermediate.push(startNode); - + for (i = 0, n = steps.length; i < n; i++) { step = steps[i]; nextStage = new Pathology.XPathResult(resultType); for (j = 0, m = intermediate._nodes.length; j < m; j++) { step.evaluate(intermediate._nodes[j], root, resultType, nextStage); } intermediate = nextStage; } - + for (i = 0, n = intermediate._nodes.length; i < n; i++) result.push(intermediate._nodes[i]); - + return result; } }; Pathology.XPathParser.LocationStep = { isRelative: function() { return this.elements[0].textValue !== '/'; }, - + evaluate: function(context, root, resultType, result) { var axis = this.selector.axis, test = this.selector.test, levels = [[]]; - + Pathology.Axis.fromAST(axis).walk(context, function(node) { if (!test || !test.evaluate) return result.push(node); test.evaluate(node, this.predicates, root, resultType, levels, result); }, this); } @@ -3088,11 +3088,11 @@ Pathology.XPathParser.NodeTest = { evaluate: function(context, predicates, root, resultType, levels, result) { var name = this.elements[0].condition_name, tagName = tagName = this.elements[0].textValue.toLowerCase(); - + var first = { expression: { evaluate: function() { if (name && name.textValue === 'node') { return true; @@ -3109,29 +3109,29 @@ return true; } }, subscript: this.subscript }; - + predicates = [first].concat(predicates.elements); var accepted, predicate; - + for (var i = 0, n = predicates.length; i < n; i++) { levels[i] = levels[i] || []; predicate = predicates[i]; - + accepted = Pathology.atomize(predicate.expression, context, root); if (typeof accepted === 'string') accepted = true; if (!accepted) return; - + levels[i].push(context); - + if (predicate.subscript.integer) { if (predicate.subscript.integer.evaluate() !== levels[i].length) return; } } - + result.push(context); } }; @@ -3159,16 +3159,16 @@ Pathology.XPathParser.Union = { evaluate: function(context, root, resultType, result) { result = result || new Pathology.XPathResult(XPathResult.ANY_TYPE); resultType = resultType || XPathResult.ANY_TYPE; - + this.head.evaluate(context, root, resultType, result); - + var sections = this.rest.elements; for (var i = 0, n = sections.length; i < n; i++) sections[i].location_path.evaluate(context, root, resultType, result); - + return result; } };