|
|
@@ -1,16 +1,3 @@
|
|
|
-// TODO: This file was created by bulk-decaffeinate.
|
|
|
-// Sanity-check the conversion and remove this comment.
|
|
|
-/*
|
|
|
- * decaffeinate suggestions:
|
|
|
- * DS101: Remove unnecessary use of Array.from
|
|
|
- * DS102: Remove unnecessary code created because of implicit returns
|
|
|
- * DS104: Avoid inline assignments
|
|
|
- * DS202: Simplify dynamic range loops
|
|
|
- * DS206: Consider reworking classes to avoid initClass
|
|
|
- * DS207: Consider shorter variations of null checks
|
|
|
- * DS209: Avoid top-level return
|
|
|
- * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
|
- */
|
|
|
//
|
|
|
// Match functions
|
|
|
//
|
|
|
@@ -158,249 +145,226 @@ function scoreFuzzyMatch() {
|
|
|
// Searchers
|
|
|
//
|
|
|
|
|
|
-(function () {
|
|
|
- let CHUNK_SIZE = undefined;
|
|
|
- let DEFAULTS = undefined;
|
|
|
- let SEPARATORS_REGEXP = undefined;
|
|
|
- let EOS_SEPARATORS_REGEXP = undefined;
|
|
|
- let INFO_PARANTHESES_REGEXP = undefined;
|
|
|
- let EMPTY_PARANTHESES_REGEXP = undefined;
|
|
|
- let EVENT_REGEXP = undefined;
|
|
|
- let DOT_REGEXP = undefined;
|
|
|
- let WHITESPACE_REGEXP = undefined;
|
|
|
- let EMPTY_STRING = undefined;
|
|
|
- let ELLIPSIS = undefined;
|
|
|
- let STRING = undefined;
|
|
|
- app.Searcher = class Searcher extends Events {
|
|
|
- static initClass() {
|
|
|
- CHUNK_SIZE = 20000;
|
|
|
-
|
|
|
- DEFAULTS = {
|
|
|
- max_results: app.config.max_results,
|
|
|
- fuzzy_min_length: 3,
|
|
|
- };
|
|
|
-
|
|
|
- SEPARATORS_REGEXP =
|
|
|
- /#|::|:-|->|\$(?=\w)|\-(?=\w)|\:(?=\w)|\ [\/\-&]\ |:\ |\ /g;
|
|
|
- EOS_SEPARATORS_REGEXP = /(\w)[\-:]$/;
|
|
|
- INFO_PARANTHESES_REGEXP = /\ \(\w+?\)$/;
|
|
|
- EMPTY_PARANTHESES_REGEXP = /\(\)/;
|
|
|
- EVENT_REGEXP = /\ event$/;
|
|
|
- DOT_REGEXP = /\.+/g;
|
|
|
- WHITESPACE_REGEXP = /\s/g;
|
|
|
-
|
|
|
- EMPTY_STRING = "";
|
|
|
- ELLIPSIS = "...";
|
|
|
- STRING = "string";
|
|
|
- }
|
|
|
+app.Searcher = class Searcher extends Events {
|
|
|
+ static CHUNK_SIZE = 20000;
|
|
|
|
|
|
- static normalizeString(string) {
|
|
|
- return string
|
|
|
- .toLowerCase()
|
|
|
- .replace(ELLIPSIS, EMPTY_STRING)
|
|
|
- .replace(EVENT_REGEXP, EMPTY_STRING)
|
|
|
- .replace(INFO_PARANTHESES_REGEXP, EMPTY_STRING)
|
|
|
- .replace(SEPARATORS_REGEXP, SEPARATOR)
|
|
|
- .replace(DOT_REGEXP, SEPARATOR)
|
|
|
- .replace(EMPTY_PARANTHESES_REGEXP, EMPTY_STRING)
|
|
|
- .replace(WHITESPACE_REGEXP, EMPTY_STRING);
|
|
|
- }
|
|
|
+ static DEFAULTS = {
|
|
|
+ max_results: app.config.max_results,
|
|
|
+ fuzzy_min_length: 3,
|
|
|
+ };
|
|
|
|
|
|
- static normalizeQuery(string) {
|
|
|
- string = this.normalizeString(string);
|
|
|
- return string.replace(EOS_SEPARATORS_REGEXP, "$1.");
|
|
|
- }
|
|
|
+ static SEPARATORS_REGEXP =
|
|
|
+ /#|::|:-|->|\$(?=\w)|\-(?=\w)|\:(?=\w)|\ [\/\-&]\ |:\ |\ /g;
|
|
|
+ static EOS_SEPARATORS_REGEXP = /(\w)[\-:]$/;
|
|
|
+ static INFO_PARANTHESES_REGEXP = /\ \(\w+?\)$/;
|
|
|
+ static EMPTY_PARANTHESES_REGEXP = /\(\)/;
|
|
|
+ static EVENT_REGEXP = /\ event$/;
|
|
|
+ static DOT_REGEXP = /\.+/g;
|
|
|
+ static WHITESPACE_REGEXP = /\s/g;
|
|
|
+
|
|
|
+ static EMPTY_STRING = "";
|
|
|
+ static ELLIPSIS = "...";
|
|
|
+ static STRING = "string";
|
|
|
+
|
|
|
+ static normalizeString(string) {
|
|
|
+ return string
|
|
|
+ .toLowerCase()
|
|
|
+ .replace(Searcher.ELLIPSIS, Searcher.EMPTY_STRING)
|
|
|
+ .replace(Searcher.EVENT_REGEXP, Searcher.EMPTY_STRING)
|
|
|
+ .replace(Searcher.INFO_PARANTHESES_REGEXP, Searcher.EMPTY_STRING)
|
|
|
+ .replace(Searcher.SEPARATORS_REGEXP, SEPARATOR)
|
|
|
+ .replace(Searcher.DOT_REGEXP, SEPARATOR)
|
|
|
+ .replace(Searcher.EMPTY_PARANTHESES_REGEXP, Searcher.EMPTY_STRING)
|
|
|
+ .replace(Searcher.WHITESPACE_REGEXP, Searcher.EMPTY_STRING);
|
|
|
+ }
|
|
|
|
|
|
- constructor(options) {
|
|
|
- super();
|
|
|
- this.options = $.extend({}, DEFAULTS, options || {});
|
|
|
- }
|
|
|
+ static normalizeQuery(string) {
|
|
|
+ string = this.normalizeString(string);
|
|
|
+ return string.replace(Searcher.EOS_SEPARATORS_REGEXP, "$1.");
|
|
|
+ }
|
|
|
|
|
|
- find(data, attr, q) {
|
|
|
- this.kill();
|
|
|
+ constructor(options) {
|
|
|
+ super();
|
|
|
+ this.options = $.extend({}, Searcher.DEFAULTS, options || {});
|
|
|
+ }
|
|
|
|
|
|
- this.data = data;
|
|
|
- this.attr = attr;
|
|
|
- this.query = q;
|
|
|
- this.setup();
|
|
|
+ find(data, attr, q) {
|
|
|
+ this.kill();
|
|
|
|
|
|
- if (this.isValid()) {
|
|
|
- this.match();
|
|
|
- } else {
|
|
|
- this.end();
|
|
|
- }
|
|
|
- }
|
|
|
+ this.data = data;
|
|
|
+ this.attr = attr;
|
|
|
+ this.query = q;
|
|
|
+ this.setup();
|
|
|
|
|
|
- setup() {
|
|
|
- query = this.query = this.constructor.normalizeQuery(this.query);
|
|
|
- queryLength = query.length;
|
|
|
- this.dataLength = this.data.length;
|
|
|
- this.matchers = [exactMatch];
|
|
|
- this.totalResults = 0;
|
|
|
- this.setupFuzzy();
|
|
|
+ if (this.isValid()) {
|
|
|
+ this.match();
|
|
|
+ } else {
|
|
|
+ this.end();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- setupFuzzy() {
|
|
|
- if (queryLength >= this.options.fuzzy_min_length) {
|
|
|
- fuzzyRegexp = this.queryToFuzzyRegexp(query);
|
|
|
- this.matchers.push(fuzzyMatch);
|
|
|
- } else {
|
|
|
- fuzzyRegexp = null;
|
|
|
- }
|
|
|
- }
|
|
|
+ setup() {
|
|
|
+ query = this.query = this.constructor.normalizeQuery(this.query);
|
|
|
+ queryLength = query.length;
|
|
|
+ this.dataLength = this.data.length;
|
|
|
+ this.matchers = [exactMatch];
|
|
|
+ this.totalResults = 0;
|
|
|
+ this.setupFuzzy();
|
|
|
+ }
|
|
|
|
|
|
- isValid() {
|
|
|
- return queryLength > 0 && query !== SEPARATOR;
|
|
|
+ setupFuzzy() {
|
|
|
+ if (queryLength >= this.options.fuzzy_min_length) {
|
|
|
+ fuzzyRegexp = this.queryToFuzzyRegexp(query);
|
|
|
+ this.matchers.push(fuzzyMatch);
|
|
|
+ } else {
|
|
|
+ fuzzyRegexp = null;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- end() {
|
|
|
- if (!this.totalResults) {
|
|
|
- this.triggerResults([]);
|
|
|
- }
|
|
|
- this.trigger("end");
|
|
|
- this.free();
|
|
|
- }
|
|
|
+ isValid() {
|
|
|
+ return queryLength > 0 && query !== SEPARATOR;
|
|
|
+ }
|
|
|
|
|
|
- kill() {
|
|
|
- if (this.timeout) {
|
|
|
- clearTimeout(this.timeout);
|
|
|
- this.free();
|
|
|
- }
|
|
|
+ end() {
|
|
|
+ if (!this.totalResults) {
|
|
|
+ this.triggerResults([]);
|
|
|
}
|
|
|
+ this.trigger("end");
|
|
|
+ this.free();
|
|
|
+ }
|
|
|
|
|
|
- free() {
|
|
|
- this.data =
|
|
|
- this.attr =
|
|
|
- this.dataLength =
|
|
|
- this.matchers =
|
|
|
- this.matcher =
|
|
|
- this.query =
|
|
|
- this.totalResults =
|
|
|
- this.scoreMap =
|
|
|
- this.cursor =
|
|
|
- this.timeout =
|
|
|
- null;
|
|
|
+ kill() {
|
|
|
+ if (this.timeout) {
|
|
|
+ clearTimeout(this.timeout);
|
|
|
+ this.free();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- match() {
|
|
|
- if (!this.foundEnough() && (this.matcher = this.matchers.shift())) {
|
|
|
- this.setupMatcher();
|
|
|
- this.matchChunks();
|
|
|
- } else {
|
|
|
- this.end();
|
|
|
- }
|
|
|
- }
|
|
|
+ free() {
|
|
|
+ this.data = null;
|
|
|
+ this.attr = null;
|
|
|
+ this.dataLength = null;
|
|
|
+ this.matchers = null;
|
|
|
+ this.matcher = null;
|
|
|
+ this.query = null;
|
|
|
+ this.totalResults = null;
|
|
|
+ this.scoreMap = null;
|
|
|
+ this.cursor = null;
|
|
|
+ this.timeout = null;
|
|
|
+ }
|
|
|
|
|
|
- setupMatcher() {
|
|
|
- this.cursor = 0;
|
|
|
- this.scoreMap = new Array(101);
|
|
|
+ match() {
|
|
|
+ if (!this.foundEnough() && (this.matcher = this.matchers.shift())) {
|
|
|
+ this.setupMatcher();
|
|
|
+ this.matchChunks();
|
|
|
+ } else {
|
|
|
+ this.end();
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- matchChunks() {
|
|
|
- this.matchChunk();
|
|
|
+ setupMatcher() {
|
|
|
+ this.cursor = 0;
|
|
|
+ this.scoreMap = new Array(101);
|
|
|
+ }
|
|
|
|
|
|
- if (this.cursor === this.dataLength || this.scoredEnough()) {
|
|
|
- this.delay(() => this.match());
|
|
|
- this.sendResults();
|
|
|
- } else {
|
|
|
- this.delay(() => this.matchChunks());
|
|
|
- }
|
|
|
+ matchChunks() {
|
|
|
+ this.matchChunk();
|
|
|
+
|
|
|
+ if (this.cursor === this.dataLength || this.scoredEnough()) {
|
|
|
+ this.delay(() => this.match());
|
|
|
+ this.sendResults();
|
|
|
+ } else {
|
|
|
+ this.delay(() => this.matchChunks());
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- matchChunk() {
|
|
|
- ({ matcher } = this);
|
|
|
- for (
|
|
|
- let j = 0, end = this.chunkSize(), asc = 0 <= end;
|
|
|
- asc ? j < end : j > end;
|
|
|
- asc ? j++ : j--
|
|
|
- ) {
|
|
|
- value = this.data[this.cursor][this.attr];
|
|
|
- if (value.split) {
|
|
|
- // string
|
|
|
+ matchChunk() {
|
|
|
+ ({ matcher } = this);
|
|
|
+ for (let j = 0, end = this.chunkSize(); j < end; j++) {
|
|
|
+ value = this.data[this.cursor][this.attr];
|
|
|
+ if (value.split) {
|
|
|
+ // string
|
|
|
+ valueLength = value.length;
|
|
|
+ if ((score = matcher())) {
|
|
|
+ this.addResult(this.data[this.cursor], score);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // array
|
|
|
+ score = 0;
|
|
|
+ for (value of Array.from(this.data[this.cursor][this.attr])) {
|
|
|
valueLength = value.length;
|
|
|
- if ((score = matcher())) {
|
|
|
- this.addResult(this.data[this.cursor], score);
|
|
|
- }
|
|
|
- } else {
|
|
|
- // array
|
|
|
- score = 0;
|
|
|
- for (value of Array.from(this.data[this.cursor][this.attr])) {
|
|
|
- valueLength = value.length;
|
|
|
- score = Math.max(score, matcher() || 0);
|
|
|
- }
|
|
|
- if (score > 0) {
|
|
|
- this.addResult(this.data[this.cursor], score);
|
|
|
- }
|
|
|
+ score = Math.max(score, matcher() || 0);
|
|
|
+ }
|
|
|
+ if (score > 0) {
|
|
|
+ this.addResult(this.data[this.cursor], score);
|
|
|
}
|
|
|
- this.cursor++;
|
|
|
}
|
|
|
+ this.cursor++;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- chunkSize() {
|
|
|
- if (this.cursor + CHUNK_SIZE > this.dataLength) {
|
|
|
- return this.dataLength % CHUNK_SIZE;
|
|
|
- } else {
|
|
|
- return CHUNK_SIZE;
|
|
|
- }
|
|
|
+ chunkSize() {
|
|
|
+ if (this.cursor + Searcher.CHUNK_SIZE > this.dataLength) {
|
|
|
+ return this.dataLength % Searcher.CHUNK_SIZE;
|
|
|
+ } else {
|
|
|
+ return Searcher.CHUNK_SIZE;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- scoredEnough() {
|
|
|
- return (
|
|
|
- (this.scoreMap[100] != null ? this.scoreMap[100].length : undefined) >=
|
|
|
- this.options.max_results
|
|
|
- );
|
|
|
- }
|
|
|
+ scoredEnough() {
|
|
|
+ return (
|
|
|
+ (this.scoreMap[100] != null ? this.scoreMap[100].length : undefined) >=
|
|
|
+ this.options.max_results
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- foundEnough() {
|
|
|
- return this.totalResults >= this.options.max_results;
|
|
|
- }
|
|
|
+ foundEnough() {
|
|
|
+ return this.totalResults >= this.options.max_results;
|
|
|
+ }
|
|
|
|
|
|
- addResult(object, score) {
|
|
|
- let name;
|
|
|
- (
|
|
|
- this.scoreMap[(name = Math.round(score))] || (this.scoreMap[name] = [])
|
|
|
- ).push(object);
|
|
|
- this.totalResults++;
|
|
|
- }
|
|
|
+ addResult(object, score) {
|
|
|
+ let name;
|
|
|
+ (
|
|
|
+ this.scoreMap[(name = Math.round(score))] || (this.scoreMap[name] = [])
|
|
|
+ ).push(object);
|
|
|
+ this.totalResults++;
|
|
|
+ }
|
|
|
|
|
|
- getResults() {
|
|
|
- const results = [];
|
|
|
- for (let j = this.scoreMap.length - 1; j >= 0; j--) {
|
|
|
- var objects = this.scoreMap[j];
|
|
|
- if (objects) {
|
|
|
- results.push.apply(results, objects);
|
|
|
- }
|
|
|
+ getResults() {
|
|
|
+ const results = [];
|
|
|
+ for (let j = this.scoreMap.length - 1; j >= 0; j--) {
|
|
|
+ var objects = this.scoreMap[j];
|
|
|
+ if (objects) {
|
|
|
+ results.push.apply(results, objects);
|
|
|
}
|
|
|
- return results.slice(0, this.options.max_results);
|
|
|
}
|
|
|
+ return results.slice(0, this.options.max_results);
|
|
|
+ }
|
|
|
|
|
|
- sendResults() {
|
|
|
- const results = this.getResults();
|
|
|
- if (results.length) {
|
|
|
- this.triggerResults(results);
|
|
|
- }
|
|
|
+ sendResults() {
|
|
|
+ const results = this.getResults();
|
|
|
+ if (results.length) {
|
|
|
+ this.triggerResults(results);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- triggerResults(results) {
|
|
|
- this.trigger("results", results);
|
|
|
- }
|
|
|
+ triggerResults(results) {
|
|
|
+ this.trigger("results", results);
|
|
|
+ }
|
|
|
|
|
|
- delay(fn) {
|
|
|
- return (this.timeout = setTimeout(fn, 1));
|
|
|
- }
|
|
|
+ delay(fn) {
|
|
|
+ return (this.timeout = setTimeout(fn, 1));
|
|
|
+ }
|
|
|
|
|
|
- queryToFuzzyRegexp(string) {
|
|
|
- const chars = string.split("");
|
|
|
- for (i = 0; i < chars.length; i++) {
|
|
|
- var char = chars[i];
|
|
|
- chars[i] = $.escapeRegexp(char);
|
|
|
- }
|
|
|
- return new RegExp(chars.join(".*?")); // abc -> /a.*?b.*?c.*?/
|
|
|
+ queryToFuzzyRegexp(string) {
|
|
|
+ const chars = string.split("");
|
|
|
+ for (i = 0; i < chars.length; i++) {
|
|
|
+ var char = chars[i];
|
|
|
+ chars[i] = $.escapeRegexp(char);
|
|
|
}
|
|
|
- };
|
|
|
- app.Searcher.initClass();
|
|
|
- return app.Searcher;
|
|
|
-})();
|
|
|
+ return new RegExp(chars.join(".*?")); // abc -> /a.*?b.*?c.*?/
|
|
|
+ }
|
|
|
+};
|
|
|
|
|
|
app.SynchronousSearcher = class SynchronousSearcher extends app.Searcher {
|
|
|
match() {
|