From 17b7fbe58d345d2f72d564ea8f7e60f4a5aaf34c Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Tue, 10 May 2016 23:40:58 +0200 Subject: [PATCH] Add support for query.one, mixins, and DOM queries, and make the Riot query optional --- src/index.js | 97 +++++++++++++++++++++++++++++++++++-------------- src/query.pegjs | 2 +- 2 files changed, 71 insertions(+), 28 deletions(-) diff --git a/src/index.js b/src/index.js index 03afec0..75b6b0f 100644 --- a/src/index.js +++ b/src/index.js @@ -29,52 +29,95 @@ function recurseTags(tag) { function createQuery(query) { let {riotQuery, domQuery} = queryParser.parse(query); - let flattenedQueries = flatten(riotQuery); - tagQueries(flattenedQueries); + let tagObtainer; - return function traverse(tag) { - let results = []; + if (riotQuery != null) { + let flattenedQueries = flatten(riotQuery); + tagQueries(flattenedQueries); + + tagObtainer = function(tag) { + let results = []; + + flattenedQueries.forEach((subQuery) => { + let lastFound = [tag]; - flattenedQueries.forEach((subQuery) => { - let lastFound = [tag]; + subQuery.forEach((segment) => { + let nextLastFound = []; - subQuery.forEach((segment) => { - let nextLastFound = []; + lastFound.forEach((subTag) => { + //console.log("subtag", subQuery, segment, subTag); + let found; - lastFound.forEach((subTag) => { - //console.log("subtag", subQuery, segment, subTag); - let found; + if (segment.type === "identifier") { + found = ensureArray(subTag.tags[segment.value]); + } else if (segment.type === "wildcard") { + found = recurseTags(subTag); + } - if (segment.type === "identifier") { - found = ensureArray(subTag.tags[segment.value]); - } else if (segment.type === "wildcard") { - found = recurseTags(subTag); - } + if (found.length > 0) { + nextLastFound = nextLastFound.concat(found) + } + }); - if (found.length > 0) { - nextLastFound = nextLastFound.concat(found) - } + lastFound = nextLastFound; }); - lastFound = nextLastFound; + results = results.concat(lastFound); }); - results = results.concat(lastFound); - }); + return dedupe(results, result => result._riot_id); + } + } else { + tagObtainer = function(tag) { + return [tag]; + } + } + + return function traverse(tag) { + let riotResults = tagObtainer(tag); - return dedupe(results, result => result._riot_id); + if (domQuery == null) { + return riotResults; + } else { + let domElements = []; + + riotResults.forEach((foundTag) => { + domElements = domElements.concat(Array.from(foundTag.root.querySelectorAll(domQuery))); + }); + + return domElements; + } } } let queryCache = {}; -module.exports = function(tag, query) { - if (queryCache[query] == null) { - queryCache[query] = createQuery(query); +function query(tag, queryString) { + if (queryCache[queryString] == null) { + queryCache[queryString] = createQuery(queryString); } // TODO: DOM traversal - return queryCache[query](tag); + return queryCache[queryString](tag); +} + +query.one = function queryOne(tag, queryString) { + let results = query(tag, queryString); + + if (results.length === 0) { + throw new Error(`No matches found for query ${queryString}`); + } else { + return results[0]; + } +} + +/* For use with `riot.mixin(query.mixin)`: */ +query.mixin = { + init: function() { + this.query = query.bind(null, this); + this.queryOne = query.one.bind(null, this); + } } +module.exports = query; \ No newline at end of file diff --git a/src/query.pegjs b/src/query.pegjs index b66d30d..3704273 100644 --- a/src/query.pegjs +++ b/src/query.pegjs @@ -19,7 +19,7 @@ } start - = riotQuery:riotQuery domQuery:domQuerySuffix? { return combineFinal(riotQuery, domQuery) } + = riotQuery:riotQuery? domQuery:domQuerySuffix? { return combineFinal(riotQuery, domQuery) } riotQuery = segment:riotQuerySegment subSegments:("/" riotQuerySegment)* { return concatRepeat(segment, subSegments, 1); }