UNPKG

grasp-squery

Version:

Grasp query backend using css style selectors

523 lines (522 loc) 17.9 kB
// Generated by LiveScript 1.4.0 (function(){ var ref$, map, any, all, literalMap, syntaxFlat, Cache, visitPre, visitChildren, getPath, toString$ = {}.toString, slice$ = [].slice; ref$ = require('prelude-ls'), map = ref$.map, any = ref$.any, all = ref$.all; ref$ = require('grasp-syntax-javascript'), literalMap = ref$.literalMap, syntaxFlat = ref$.syntaxFlat; ref$ = require('./common'), Cache = ref$.Cache, visitPre = ref$.visitPre, visitChildren = ref$.visitChildren, getPath = ref$.getPath; function finalMatches(results){ var matches, i$, ref$, len$, subjects; matches = []; if (results.subject.length > 0) { for (i$ = 0, len$ = (ref$ = results.subject).length; i$ < len$; ++i$) { subjects = ref$[i$]; matches = matches.concat(subjects); } } else { matches = results.matches; } return matches; } function matchAst(ast, selector, cache){ var subject, matches, isSubject, i$, ref$, len$, node, selVal, name, op, value, valueType, sel, left, props, subjects, leftResults, leftSubject, result, subs, propsLen, hasMatch, previousNode, j$, len1$, i, prop, newNode, k$, len2$, p, nodeInfo, l$, len3$, field, res$, propValue, ref1$, sub, ref2$, matchesSelector, ref3$, rightResults, leftMatches, rightSubject, rightMatches, leftI, leftNode; subject = []; matches = []; if (!selector) { return { subject: subject, matches: matches }; } isSubject = selector.subject; switch (selector.type) { case 'wildcard': for (i$ = 0, len$ = (ref$ = cache.nodes).length; i$ < len$; ++i$) { node = ref$[i$]; matches.push(node); if (isSubject) { subject.push([node]); } } break; case 'root': matches.push(ast); if (isSubject) { subject.push([ast]); } break; case 'identifier': if (cache.types.hasOwnProperty(selector.value)) { for (i$ = 0, len$ = (ref$ = cache.types[selector.value]).length; i$ < len$; ++i$) { node = ref$[i$]; matches.push(node); if (isSubject) { subject.push([node]); } } } break; case 'nth-child': visitPre(ast, function(node){ var index, i$, val, len; index = selector.index.value; for (i$ in node) { val = node[i$]; if (toString$.call(val).slice(8, -1) === 'Array') { len = val.length; if (0 <= index && index < len) { matches.push(val[index]); if (isSubject) { subject.push([val[index]]); } } } } }); break; case 'nth-last-child': visitPre(ast, function(node){ var index, i$, val, len, i; index = selector.index.value; for (i$ in node) { val = node[i$]; if (toString$.call(val).slice(8, -1) === 'Array') { len = val.length; i = len - index - 1; if (0 <= i && i < len) { matches.push(val[i]); if (isSubject) { subject.push([val[i]]); } } } } }); break; case 'attribute': selVal = selector.value; name = selector.name; if (selVal != null) { op = selector.operator; value = selVal.value; valueType = toString$.call(value).slice(8, -1); switch (selector.valType) { case 'primitive': switch (selVal.type) { case 'literal': visitPre(ast, function(node){ if (isMatchPrimitiveLiteral(getPath(node, name), op, value, valueType)) { matches.push(node); if (isSubject) { subject.push([node]); } } }); break; case 'type': visitPre(ast, function(node){ if (isMatchType(getPath(node, name), op, value)) { matches.push(node); if (isSubject) { subject.push([node]); } } }); } break; case 'either': sel = selVal.sel; visitPre(ast, function(node){ var nodeValue; nodeValue = getPath(node, name); if ('object' === typeof nodeValue && (nodeValue != null && nodeValue.type) && isMatchComplex(nodeValue, op, value, sel) || isMatchPrimitiveLiteral(nodeValue, op, value, valueType)) { matches.push(node); if (isSubject) { subject.push([node]); } } }); break; case 'complex': visitPre(ast, function(node){ if (isMatchComplex(getPath(node, name), op, value, selVal)) { matches.push(node); if (isSubject) { subject.push([node]); } } }); } } else { visitPre(ast, function(node){ if (getPath(node, name) != null) { matches.push(node); if (isSubject) { subject.push([node]); } } }); } break; case 'prop': left = selector.left, props = selector.props, subjects = selector.subjects; leftResults = finalMatches(matchAst(ast, left, cache)); leftSubject = left.subject; for (i$ = 0, len$ = leftResults.length; i$ < len$; ++i$) { result = leftResults[i$]; node = result; subs = []; propsLen = props.length; hasMatch = false; for (j$ = 0, len1$ = props.length; j$ < len1$; ++j$) { i = j$; prop = props[j$]; previousNode = node; if (prop.type === 'wildcard') { if (toString$.call(node).slice(8, -1) === 'Array') { newNode = []; for (k$ = 0, len2$ = node.length; k$ < len2$; ++k$) { p = node[k$]; nodeInfo = syntaxFlat[p.type]; if (nodeInfo != null) { for (l$ = 0, len3$ = (ref$ = nodeInfo.nodes.concat(nodeInfo.nodeArrays)).length; l$ < len3$; ++l$) { field = ref$[l$]; if (p[field] != null) { newNode.push(p[field]); } } } } node = newNode; } else { nodeInfo = syntaxFlat[node.type]; if (nodeInfo != null) { res$ = []; for (k$ = 0, len2$ = (ref$ = nodeInfo.nodes.concat(nodeInfo.nodeArrays)).length; k$ < len2$; ++k$) { field = ref$[k$]; if (node[field] != null) { res$.push(node[field]); } } node = res$; } } } else if (prop.type === 'string') { propValue = prop.value; if (toString$.call(node).slice(8, -1) === 'Array') { res$ = []; for (k$ = 0, len2$ = node.length; k$ < len2$; ++k$) { p = node[k$]; if (p[propValue] != null) { res$.push(p[propValue]); } } node = res$; } else { node = node[propValue]; } } else if (toString$.call(node).slice(8, -1) === 'Array') { switch (prop.type) { case 'first': case 'head': node = node[0]; break; case 'tail': node = node.slice(1); break; case 'last': node = node[node.length - 1]; break; case 'initial': node = node.slice(0, node.length - 1); break; case 'nth': node = node[prop.index.value]; break; case 'nth-last': node = node[node.length - prop.index.value - 1]; break; case 'slice': node = node.slice.apply(node, map(fn$, prop.indicies)); } } else { break; } if (node == null) { break; } if (toString$.call(node).slice(8, -1) === 'String' && prop.value === 'operator') { node = { type: 'Operator', value: node, loc: { start: (ref$ = previousNode.left.loc) != null ? ref$.end : void 8, end: (ref1$ = previousNode.right.loc) != null ? ref1$.start : void 8 }, raw: node }; } if (node.type != null) { if (subjects[i]) { subs.push(node); } } else if (toString$.call(node).slice(8, -1) === 'Array' && node.length) { if (subjects[i]) { subs = subs.concat(node); } } else { break; } if (i === propsLen - 1) { hasMatch = true; } } if (hasMatch) { if (toString$.call(node).slice(8, -1) === 'Array') { matches = matches.concat(node); } else { matches.push(node); } if (leftSubject) { subject.push([result]); } if (subs.length) { for (j$ = 0, len1$ = subs.length; j$ < len1$; ++j$) { sub = subs[j$]; subject.push([sub]); } } } } break; case 'matches': for (i$ = 0, len$ = (ref2$ = selector.selectors).length; i$ < len$; ++i$) { matchesSelector = ref2$[i$]; for (j$ = 0, len1$ = (ref3$ = finalMatches(matchAst(ast, matchesSelector, cache))).length; j$ < len1$; ++j$) { node = ref3$[j$]; matches.push(node); if (isSubject) { subject.push([node]); } } } break; case 'not': rightResults = []; for (i$ = 0, len$ = (ref2$ = selector.selectors).length; i$ < len$; ++i$) { sel = ref2$[i$]; rightResults = rightResults.concat(finalMatches(matchAst(ast, sel, cache))); } visitPre(ast, function(node){ if (!in$(node, rightResults)) { matches.push(node); if (isSubject) { subject.push([node]); } } }); break; case 'compound': res$ = []; for (i$ = 0, len$ = (ref2$ = selector.selectors).length; i$ < len$; ++i$) { sel = ref2$[i$]; res$.push(finalMatches(matchAst(ast, sel, cache))); } rightResults = res$; isSubject = isSubject || any(function(it){ return it.subject; }, selector.selectors); for (i$ = 0, len$ = (ref2$ = rightResults[0]).length; i$ < len$; ++i$) { node = ref2$[i$]; if (all((fn1$), slice$.call(rightResults, 1))) { matches.push(node); if (isSubject) { subject.push([node]); } } } break; case 'descendant': ref2$ = matchAst(ast, selector.left, cache), leftSubject = ref2$.subject, leftMatches = ref2$.matches; ref2$ = matchAst(ast, selector.right, cache), rightSubject = ref2$.subject, rightMatches = ref2$.matches; for (i$ = 0, len$ = leftMatches.length; i$ < len$; ++i$) { leftI = i$; leftNode = leftMatches[i$]; visitPre(leftNode, fn2$); } break; case 'child': ref2$ = matchAst(ast, selector.left, cache), leftSubject = ref2$.subject, leftMatches = ref2$.matches; ref2$ = matchAst(ast, selector.right, cache), rightSubject = ref2$.subject, rightMatches = ref2$.matches; for (i$ = 0, len$ = leftMatches.length; i$ < len$; ++i$) { leftI = i$; leftNode = leftMatches[i$]; visitChildren(leftNode, fn3$); } break; case 'sibling': ref2$ = matchAst(ast, selector.left, cache), leftSubject = ref2$.subject, leftMatches = ref2$.matches; ref2$ = matchAst(ast, selector.right, cache), rightSubject = ref2$.subject, rightMatches = ref2$.matches; visitPre(ast, function(node, context){ var key, val, i$, len$, i, x, leftI, j, rightI, newSubject, that; for (key in node) { val = node[key]; if (toString$.call(val).slice(8, -1) === 'Array') { for (i$ = 0, len$ = val.length; i$ < len$; ++i$) { i = i$; x = val[i$]; leftI = leftMatches.indexOf(x); if (leftI > -1) { j = i + 1; for (; j < val.length; j++) { rightI = rightMatches.indexOf(val[j]); if (rightI > -1) { matches.push(val[j]); newSubject = []; if (that = leftSubject[leftI]) { newSubject = that; } if (that = rightSubject[rightI]) { newSubject = newSubject.concat(that); } if (newSubject.length > 0) { subject.push(newSubject); } } } } } } } }); break; case 'adjacent': ref2$ = matchAst(ast, selector.left, cache), leftSubject = ref2$.subject, leftMatches = ref2$.matches; ref2$ = matchAst(ast, selector.right, cache), rightSubject = ref2$.subject, rightMatches = ref2$.matches; visitPre(ast, function(node, context){ var key, val, i$, len$, i, x, leftI, rightI, newSubject, that; for (key in node) { val = node[key]; if (toString$.call(val).slice(8, -1) === 'Array') { for (i$ = 0, len$ = val.length; i$ < len$; ++i$) { i = i$; x = val[i$]; leftI = leftMatches.indexOf(x); if (leftI > -1) { rightI = rightMatches.indexOf(val[i + 1]); if (rightI > -1) { matches.push(val[i + 1]); newSubject = []; if (that = leftSubject[leftI]) { newSubject = that; } if (that = rightSubject[rightI]) { newSubject = newSubject.concat(that); } if (newSubject.length > 0) { subject.push(newSubject); } } } } } } }); } return { subject: subject, matches: matches }; function fn$(it){ return it.value; } function fn1$(it){ return in$(node, it); } function fn2$(rightNode){ var rightI, newSubject, that; if (leftNode === rightNode) { return; } rightI = rightMatches.indexOf(rightNode); if (rightI > -1) { matches.push(rightNode); newSubject = []; if (that = leftSubject[leftI]) { newSubject = that; } if (that = rightSubject[rightI]) { newSubject = newSubject.concat(that); } if (newSubject.length > 0) { subject.push(newSubject); } } } function fn3$(child){ var rightI, newSubject, that; rightI = rightMatches.indexOf(child); if (rightI > -1) { matches.push(child); newSubject = []; if (that = leftSubject[leftI]) { newSubject = that; } if (that = rightSubject[rightI]) { newSubject = newSubject.concat(that); } if (newSubject.length > 0) { subject.push(newSubject); } } } } function isMatchPrimitiveLiteral(nodeValue, op, value, valueType){ var nodeType; nodeType = toString$.call(nodeValue).slice(8, -1); if (nodeType === 'Undefined' || nodeType === 'Object') { return false; } return op === '=' && (nodeValue === value || (nodeType === valueType && valueType === 'RegExp') && nodeValue.toString() === value.toString()) || op === '!=' && (nodeType !== 'RegExp' && nodeValue !== value || (nodeType === valueType && valueType === 'RegExp') && nodeValue.toString() !== value.toString()) || (op === '=~' || op === '~=') && value.test(nodeValue) || op === '<=' && nodeValue <= value || op === '>=' && nodeValue >= value || op === '<' && nodeValue < value || op === '>' && nodeValue > value; } function isMatchType(nodeValue, op, value){ var test; test = (literalMap[value] || value).match(RegExp(toString$.call(nodeValue).slice(8, -1) + '', 'i')); return op === '=' && test || op === '!=' && !test; } function addSubjectToFirst(sel){ var ref$; if ((ref$ = sel.type) === 'descendant' || ref$ === 'child' || ref$ === 'sibling' || ref$ === 'adjacent') { return addSubjectToFirst(sel.left); } else { return sel.subject = true; } } function isMatchComplex(nodeValue, op, value, selector){ var cache, sel, subMatches, subMatchesLen; if (nodeValue == null) { return false; } cache = new Cache(nodeValue); addSubjectToFirst(selector); sel = { type: 'compound', selectors: [ selector, { type: 'root' } ] }; subMatches = finalMatches(matchAst(nodeValue, sel, cache)); subMatchesLen = subMatches.length; return op === '=' && subMatchesLen || op === '!=' && !subMatchesLen; } module.exports = { finalMatches: finalMatches, matchAst: matchAst }; function in$(x, xs){ var i = -1, l = xs.length >>> 0; while (++i < l) if (x === xs[i]) return true; return false; } }).call(this);