History

Sanity-check decaffeinate app.Searcher

Simon Legner committed 2 years ago

Commit efb36971 parent 978d4a91 file · +179 −215Browse files

Unified · Split

assets/javascripts/app/searcher.js+179−215
@@ -1,16 +1,3 @@
1// TODO: This file was created by bulk-decaffeinate.
2// Sanity-check the conversion and remove this comment.
3/*
4 * decaffeinate suggestions:
5 * DS101: Remove unnecessary use of Array.from
6 * DS102: Remove unnecessary code created because of implicit returns
7 * DS104: Avoid inline assignments
8 * DS202: Simplify dynamic range loops
9 * DS206: Consider reworking classes to avoid initClass
10 * DS207: Consider shorter variations of null checks
11 * DS209: Avoid top-level return
12 * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
13 */
14//1//
15// Match functions2// Match functions
16//3//
@@ -158,249 +145,226 @@ function scoreFuzzyMatch() { · 141 unmodified lines
158// Searchers145// Searchers
159//146//
160 147
161(function () {148app.Searcher = class Searcher extends Events {
162 let CHUNK_SIZE = undefined;149 static CHUNK_SIZE = 20000;
163 let DEFAULTS = undefined;
164 let SEPARATORS_REGEXP = undefined;
165 let EOS_SEPARATORS_REGEXP = undefined;
166 let INFO_PARANTHESES_REGEXP = undefined;
167 let EMPTY_PARANTHESES_REGEXP = undefined;
168 let EVENT_REGEXP = undefined;
169 let DOT_REGEXP = undefined;
170 let WHITESPACE_REGEXP = undefined;
171 let EMPTY_STRING = undefined;
172 let ELLIPSIS = undefined;
173 let STRING = undefined;
174 app.Searcher = class Searcher extends Events {
175 static initClass() {
176 CHUNK_SIZE = 20000;
177
178 DEFAULTS = {
179 max_results: app.config.max_results,
180 fuzzy_min_length: 3,
181 };
182
183 SEPARATORS_REGEXP =
184 /#|::|:-|->|\$(?=\w)|\-(?=\w)|\:(?=\w)|\ [\/\-&]\ |:\ |\ /g;
185 EOS_SEPARATORS_REGEXP = /(\w)[\-:]$/;
186 INFO_PARANTHESES_REGEXP = /\ \(\w+?\)$/;
187 EMPTY_PARANTHESES_REGEXP = /\(\)/;
188 EVENT_REGEXP = /\ event$/;
189 DOT_REGEXP = /\.+/g;
190 WHITESPACE_REGEXP = /\s/g;
191
192 EMPTY_STRING = "";
193 ELLIPSIS = "...";
194 STRING = "string";
195 }
196 150
197 static normalizeString(string) {151 static DEFAULTS = {
198 return string152 max_results: app.config.max_results,
199 .toLowerCase()153 fuzzy_min_length: 3,
200 .replace(ELLIPSIS, EMPTY_STRING)154 };
201 .replace(EVENT_REGEXP, EMPTY_STRING)
202 .replace(INFO_PARANTHESES_REGEXP, EMPTY_STRING)
203 .replace(SEPARATORS_REGEXP, SEPARATOR)
204 .replace(DOT_REGEXP, SEPARATOR)
205 .replace(EMPTY_PARANTHESES_REGEXP, EMPTY_STRING)
206 .replace(WHITESPACE_REGEXP, EMPTY_STRING);
207 }
208 155
209 static normalizeQuery(string) {156 static SEPARATORS_REGEXP =
210 string = this.normalizeString(string);157 /#|::|:-|->|\$(?=\w)|\-(?=\w)|\:(?=\w)|\ [\/\-&]\ |:\ |\ /g;
211 return string.replace(EOS_SEPARATORS_REGEXP, "$1.");158 static EOS_SEPARATORS_REGEXP = /(\w)[\-:]$/;
212 }159 static INFO_PARANTHESES_REGEXP = /\ \(\w+?\)$/;
160 static EMPTY_PARANTHESES_REGEXP = /\(\)/;
161 static EVENT_REGEXP = /\ event$/;
162 static DOT_REGEXP = /\.+/g;
163 static WHITESPACE_REGEXP = /\s/g;
164
165 static EMPTY_STRING = "";
166 static ELLIPSIS = "...";
167 static STRING = "string";
168
169 static normalizeString(string) {
170 return string
171 .toLowerCase()
172 .replace(Searcher.ELLIPSIS, Searcher.EMPTY_STRING)
173 .replace(Searcher.EVENT_REGEXP, Searcher.EMPTY_STRING)
174 .replace(Searcher.INFO_PARANTHESES_REGEXP, Searcher.EMPTY_STRING)
175 .replace(Searcher.SEPARATORS_REGEXP, SEPARATOR)
176 .replace(Searcher.DOT_REGEXP, SEPARATOR)
177 .replace(Searcher.EMPTY_PARANTHESES_REGEXP, Searcher.EMPTY_STRING)
178 .replace(Searcher.WHITESPACE_REGEXP, Searcher.EMPTY_STRING);
179 }
213 180
214 constructor(options) {181 static normalizeQuery(string) {
215 super();182 string = this.normalizeString(string);
216 this.options = $.extend({}, DEFAULTS, options || {});183 return string.replace(Searcher.EOS_SEPARATORS_REGEXP, "$1.");
217 }184 }
218 185
219 find(data, attr, q) {186 constructor(options) {
220 this.kill();187 super();
188 this.options = $.extend({}, Searcher.DEFAULTS, options || {});
189 }
221 190
222 this.data = data;191 find(data, attr, q) {
223 this.attr = attr;192 this.kill();
224 this.query = q;
225 this.setup();
226 193
227 if (this.isValid()) {194 this.data = data;
228 this.match();195 this.attr = attr;
229 } else {196 this.query = q;
230 this.end();197 this.setup();
231 }
232 }
233 198
234 setup() {199 if (this.isValid()) {
235 query = this.query = this.constructor.normalizeQuery(this.query);200 this.match();
236 queryLength = query.length;201 } else {
237 this.dataLength = this.data.length;202 this.end();
238 this.matchers = [exactMatch];
239 this.totalResults = 0;
240 this.setupFuzzy();
241 }203 }
204 }
242 205
243 setupFuzzy() {206 setup() {
244 if (queryLength >= this.options.fuzzy_min_length) {207 query = this.query = this.constructor.normalizeQuery(this.query);
245 fuzzyRegexp = this.queryToFuzzyRegexp(query);208 queryLength = query.length;
246 this.matchers.push(fuzzyMatch);209 this.dataLength = this.data.length;
247 } else {210 this.matchers = [exactMatch];
248 fuzzyRegexp = null;211 this.totalResults = 0;
249 }212 this.setupFuzzy();
250 }213 }
251 214
252 isValid() {215 setupFuzzy() {
253 return queryLength > 0 && query !== SEPARATOR;216 if (queryLength >= this.options.fuzzy_min_length) {
217 fuzzyRegexp = this.queryToFuzzyRegexp(query);
218 this.matchers.push(fuzzyMatch);
219 } else {
220 fuzzyRegexp = null;
254 }221 }
222 }
255 223
256 end() {224 isValid() {
257 if (!this.totalResults) {225 return queryLength > 0 && query !== SEPARATOR;
258 this.triggerResults([]);226 }
259 }
260 this.trigger("end");
261 this.free();
262 }
263 227
264 kill() {228 end() {
265 if (this.timeout) {229 if (!this.totalResults) {
266 clearTimeout(this.timeout);230 this.triggerResults([]);
267 this.free();
268 }
269 }231 }
232 this.trigger("end");
233 this.free();
234 }
270 235
271 free() {236 kill() {
272 this.data =237 if (this.timeout) {
273 this.attr =238 clearTimeout(this.timeout);
274 this.dataLength =239 this.free();
275 this.matchers =
276 this.matcher =
277 this.query =
278 this.totalResults =
279 this.scoreMap =
280 this.cursor =
281 this.timeout =
282 null;
283 }240 }
241 }
284 242
285 match() {243 free() {
286 if (!this.foundEnough() && (this.matcher = this.matchers.shift())) {244 this.data = null;
287 this.setupMatcher();245 this.attr = null;
288 this.matchChunks();246 this.dataLength = null;
289 } else {247 this.matchers = null;
290 this.end();248 this.matcher = null;
291 }249 this.query = null;
292 }250 this.totalResults = null;
251 this.scoreMap = null;
252 this.cursor = null;
253 this.timeout = null;
254 }
293 255
294 setupMatcher() {256 match() {
295 this.cursor = 0;257 if (!this.foundEnough() && (this.matcher = this.matchers.shift())) {
296 this.scoreMap = new Array(101);258 this.setupMatcher();
259 this.matchChunks();
260 } else {
261 this.end();
297 }262 }
263 }
298 264
299 matchChunks() {265 setupMatcher() {
300 this.matchChunk();266 this.cursor = 0;
267 this.scoreMap = new Array(101);
268 }
301 269
302 if (this.cursor === this.dataLength || this.scoredEnough()) {270 matchChunks() {
303 this.delay(() => this.match());271 this.matchChunk();
304 this.sendResults();272
305 } else {273 if (this.cursor === this.dataLength || this.scoredEnough()) {
306 this.delay(() => this.matchChunks());274 this.delay(() => this.match());
307 }275 this.sendResults();
276 } else {
277 this.delay(() => this.matchChunks());
308 }278 }
279 }
309 280
310 matchChunk() {281 matchChunk() {
311 ({ matcher } = this);282 ({ matcher } = this);
312 for (283 for (let j = 0, end = this.chunkSize(); j < end; j++) {
313 let j = 0, end = this.chunkSize(), asc = 0 <= end;284 value = this.data[this.cursor][this.attr];
314 asc ? j < end : j > end;285 if (value.split) {
315 asc ? j++ : j--286 // string
316 ) {287 valueLength = value.length;
317 value = this.data[this.cursor][this.attr];288 if ((score = matcher())) {
318 if (value.split) {289 this.addResult(this.data[this.cursor], score);
319 // string290 }
291 } else {
292 // array
293 score = 0;
294 for (value of Array.from(this.data[this.cursor][this.attr])) {
320 valueLength = value.length;295 valueLength = value.length;
321 if ((score = matcher())) {296 score = Math.max(score, matcher() || 0);
322 this.addResult(this.data[this.cursor], score);297 }
323 }298 if (score > 0) {
324 } else {299 this.addResult(this.data[this.cursor], score);
325 // array
326 score = 0;
327 for (value of Array.from(this.data[this.cursor][this.attr])) {
328 valueLength = value.length;
329 score = Math.max(score, matcher() || 0);
330 }
331 if (score > 0) {
332 this.addResult(this.data[this.cursor], score);
333 }
334 }300 }
335 this.cursor++;
336 }301 }
302 this.cursor++;
337 }303 }
304 }
338 305
339 chunkSize() {306 chunkSize() {
340 if (this.cursor + CHUNK_SIZE > this.dataLength) {307 if (this.cursor + Searcher.CHUNK_SIZE > this.dataLength) {
341 return this.dataLength % CHUNK_SIZE;308 return this.dataLength % Searcher.CHUNK_SIZE;
342 } else {309 } else {
343 return CHUNK_SIZE;310 return Searcher.CHUNK_SIZE;
344 }
345 }311 }
312 }
346 313
347 scoredEnough() {314 scoredEnough() {
348 return (315 return (
349 (this.scoreMap[100] != null ? this.scoreMap[100].length : undefined) >=316 (this.scoreMap[100] != null ? this.scoreMap[100].length : undefined) >=
350 this.options.max_results317 this.options.max_results
351 );318 );
352 }319 }
353 320
354 foundEnough() {321 foundEnough() {
355 return this.totalResults >= this.options.max_results;322 return this.totalResults >= this.options.max_results;
356 }323 }
357 324
358 addResult(object, score) {325 addResult(object, score) {
359 let name;326 let name;
360 (327 (
361 this.scoreMap[(name = Math.round(score))] || (this.scoreMap[name] = [])328 this.scoreMap[(name = Math.round(score))] || (this.scoreMap[name] = [])
362 ).push(object);329 ).push(object);
363 this.totalResults++;330 this.totalResults++;
364 }331 }
365 332
366 getResults() {333 getResults() {
367 const results = [];334 const results = [];
368 for (let j = this.scoreMap.length - 1; j >= 0; j--) {335 for (let j = this.scoreMap.length - 1; j >= 0; j--) {
369 var objects = this.scoreMap[j];336 var objects = this.scoreMap[j];
370 if (objects) {337 if (objects) {
371 results.push.apply(results, objects);338 results.push.apply(results, objects);
372 }
373 }339 }
374 return results.slice(0, this.options.max_results);
375 }340 }
341 return results.slice(0, this.options.max_results);
342 }
376 343
377 sendResults() {344 sendResults() {
378 const results = this.getResults();345 const results = this.getResults();
379 if (results.length) {346 if (results.length) {
380 this.triggerResults(results);347 this.triggerResults(results);
381 }
382 }348 }
349 }
383 350
384 triggerResults(results) {351 triggerResults(results) {
385 this.trigger("results", results);352 this.trigger("results", results);
386 }353 }
387 354
388 delay(fn) {355 delay(fn) {
389 return (this.timeout = setTimeout(fn, 1));356 return (this.timeout = setTimeout(fn, 1));
390 }357 }
391 358
392 queryToFuzzyRegexp(string) {359 queryToFuzzyRegexp(string) {
393 const chars = string.split("");360 const chars = string.split("");
394 for (i = 0; i < chars.length; i++) {361 for (i = 0; i < chars.length; i++) {
395 var char = chars[i];362 var char = chars[i];
396 chars[i] = $.escapeRegexp(char);363 chars[i] = $.escapeRegexp(char);
397 }
398 return new RegExp(chars.join(".*?")); // abc -> /a.*?b.*?c.*?/
399 }364 }
400 };365 return new RegExp(chars.join(".*?")); // abc -> /a.*?b.*?c.*?/
401 app.Searcher.initClass();366 }
402 return app.Searcher;367};
403})();
404 368
405app.SynchronousSearcher = class SynchronousSearcher extends app.Searcher {369app.SynchronousSearcher = class SynchronousSearcher extends app.Searcher {
406 match() {370 match() {