diff --git a/README.md b/README.md index 71e9673..195ede2 100644 --- a/README.md +++ b/README.md @@ -43,20 +43,20 @@ Get Latest (Stable Release): flexsearch.min.js - Download - https://cdn.jsdelivr.net/gh/nextapps-de/flexsearch@master/flexsearch.min.js + Download + https://cdn.jsdelivr.net/gh/nextapps-de/flexsearch@master/dist/flexsearch.min.js flexsearch.light.js - Download - https://cdn.jsdelivr.net/gh/nextapps-de/flexsearch@master/flexsearch.light.js + Download + https://cdn.jsdelivr.net/gh/nextapps-de/flexsearch@master/dist/flexsearch.light.js flexsearch.compact.js - Download - https://cdn.jsdelivr.net/gh/nextapps-de/flexsearch@master/flexsearch.compact.js + Download + https://cdn.jsdelivr.net/gh/nextapps-de/flexsearch@master/dist/flexsearch.compact.js @@ -188,7 +188,7 @@ All Features: Comparison: Benchmark "Gulliver's Travels" -__Query Test: "Gulliver's Travels"__ +##### Query Test: "Gulliver's Travels" @@ -282,7 +282,7 @@ __Query Test: "Gulliver's Travels"__
-__Memory Test: "Gulliver's Travels"__ +##### Memory Test: "Gulliver's Travels" @@ -491,15 +491,15 @@ __Note:__ This feature is actually not enabled by default. Read + ``` Or a specific version: ```html - + ``` -__AMD__ +AMD: ```javascript var FlexSearch = require("./flexsearch.js"); @@ -549,6 +549,7 @@ Index methods: - Index.__import__(string) ## Usage + #### Create a new index @@ -612,6 +613,7 @@ index.search("John", 10); #### Async Search + Perform queries asynchronously: ```js @@ -644,6 +646,7 @@ async function search(query){ ``` #### Custom Search + Pass custom options for each query: ```js @@ -673,6 +676,7 @@ index.search("John", { ``` #### Suggestions + Get also suggestions for a query: ```js @@ -1561,7 +1565,7 @@ Compare these presets: ## Best Practices -__Split Complexity__ +##### Split Complexity Whenever you can, try to divide content by categories and add them to its own index, e.g.: @@ -1616,7 +1620,7 @@ var results = search("action", "movie title"); // --> [1] Filter queries by categories will hugely improve performance. -__Use numeric IDs__ +##### Use numeric IDs It is recommended to use numeric id values as reference when adding content to the index. The byte length of passed ids influences the memory consumption significantly. If this is not possible you should consider to use a index table and map the ids with indexes, this becomes important especially when using contextual indexes on a large amount of content. @@ -1711,7 +1715,7 @@ index.stats; The returning stats payload is divided into several categories. Each of these category provides its own statistic values. -__Profiler Stats Properties__ +##### Profiler Stats Properties
@@ -1774,7 +1778,7 @@ node compile SUPPORT_WORKER=true > The custom build will be saved to flexsearch.custom.xxxxx.js (the "xxxxx" is a hash based on the used build flags). -__Supported Build Flags__ +##### Supported Build Flags
diff --git a/compile.js b/compile.js index 94b771f..1dfa757 100644 --- a/compile.js +++ b/compile.js @@ -113,12 +113,13 @@ if(release === "lang"){ } else{ - exec("java -jar node_modules/google-closure-compiler-java/compiler.jar" + parameter + "' --js='flexsearch.js' --js='lang/**.js' --js='!lang/**.min.js'" + flag_str + " --js_output_file='flexsearch." + (options["RELEASE"] || "custom") + ".js' && exit 0", function(){ + exec("java -jar node_modules/google-closure-compiler-java/compiler.jar" + parameter + "' --js='flexsearch.js' --js='lang/**.js' --js='!lang/**.min.js'" + flag_str + " --js_output_file='dist/flexsearch." + (options["RELEASE"] || "custom") + ".js' && exit 0", function(){ var filename = "flexsearch." + (options["RELEASE"] || "custom") + ".js"; console.log("Build Complete: " + filename); + /* if(release === "es5"){ //fs.existsSync("dist/") || fs.mkdirSync("dist/"); @@ -128,6 +129,7 @@ else{ //fs.copyFileSync(filename, "dist/latest/" + filename); fs.unlinkSync(filename); } + */ }); } diff --git a/dist/flexsearch.compact.js b/dist/flexsearch.compact.js new file mode 100644 index 0000000..f3739f6 --- /dev/null +++ b/dist/flexsearch.compact.js @@ -0,0 +1,23 @@ +/* + FlexSearch v0.3.51 + Copyright 2019 Nextapps GmbH + Author: Thomas Wilkerling + Released under the Apache 2.0 Licence + https://github.com/nextapps-de/flexsearch +*/ +'use strict';(function(f,r,d){let k;(k=d.define)&&k.amd?k([],function(){return r}):(k=d.modules)?k[f.toLowerCase()]=r:"object"===typeof exports?module.exports=r:d[f]=r})("FlexSearch",function(){function f(b){z(b)&&(b=F[b]);b||(b=v);this.id=b.id||L++;this.init(b);r(this,"index",function(){return this.b});r(this,"length",function(){return Object.keys(this.b).length})}function r(b,a,c){Object.defineProperty(b,a,{get:c})}function d(b){return new RegExp(b,"g")}function k(b,a){for(let c=0;c=m&&(b=b[9-(e+.5>>0)],b=b[c]||(b[c]=[]),b[b.length]=g);return e}function C(b,a){if(b){const c=Object.keys(b);for(let g=0,d=c.length;gb?1:b?-1:0}function N(b,a){b=b.length-a.length;return 0>b?-1:b?1:0}function O(b,a,c){let d=[],e;const t=b.length;if(1a&&(d=d.slice(0,a)));return d}function z(b){return"string"===typeof b}function A(b){return"function"===typeof b}function B(b){return"undefined"===typeof b}function H(b){const a= +Array(b);for(let c=0;ch;c--)n=m.substring(h,c),y(t,k,n,b,a,l,p)}break;default:if(f=y(t,k,m,b,1,l,p),q&&1=p)for(f=k._ctx[m]||(k._ctx[m]=u()),m=this.c[m]||(this.c[m]=H(10-(p||0))),l=a-q,n=a+q+1,0>l&&(l=0),n>w&&(n=w);l=c&&(this.v=this.h), +this.B&&this.v===this.h&&(this.cache&&this.o.set(a,this.l),this.B(this.l),this.l=[]));return this}function l(b,a,f){Object.defineProperty(b,a,{get:f})}function c(b){return new RegExp(b,"g")}function d(b,a){for(var f=0;f=g&&(b=b[9-(d+.5>>0)],b=b[f]||(b[f]=[]),b[b.length]=c);return d}function z(b,a){if(b)for(var f=Object.keys(b),c=0,d=f.length;cb?1:b?-1:0}function V(b,a){b=b.length-a.length;return 0>b? +-1:b?1:0}function U(b,a,f){var c=[],d=b.length;if(1a&&(c=c.slice(0,a)));return c}function C(b){return"string"===typeof b}function G(b){return"function"===typeof b}function w(b){return"undefined"===typeof b}function M(b){for(var a=Array(b),f=0;f=this.f.length&&(this.u=0),this.f[this.u].postMessage({add:!0,id:b,content:a}),this.a[e]=""+this.u,f&&f(),this;if(!d){if(this.async&& +"function"!==typeof importScripts){var g=this;e=new Promise(function(f){setTimeout(function(){g.add(b,a,null,c,!0);g=null;f()})});if(f)e.then(f);else return e;return this}if(f)return this.add(b,a,null,c,!0),f(),this}a=this.encode(a);if(!a.length)return this;f=this.g;d=G(f)?f(a):a.split(N);var h=y();h._ctx=y();for(var A=this.threshold,l=this.depth,H=this.b,r=d.length,q=0;qv;t--)p=u.substring(v,t),B(H,h,p,b,w,m,A);break;default:if(n=B(H,h,u,b,1,m,A),l&&1=A)for(n=h._ctx[u]||(h._ctx[u]=y()),u=this.c[u]||(this.c[u]=M(10-(A||0))),m=q-l,p=q+l+1,0>m&&(m=0),p>r&&(p=r);md;c--)h=g[c-1],g[c]=h,e[h]= +c;g[d]=a;e[a]=d}}}return b};return b}();return e}(function(){var g={},k="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(e,h,l,c,d){l=k?URL.createObjectURL(new Blob(["("+l.toString()+")()"],{type:"text/javascript"})):e+".es5.js";e+="-"+h;g[e]||(g[e]=[]);g[e][d]=new Worker(l);g[e][d].onmessage=c;console.log("Register Worker: "+e+"@"+d);return g[e][d]}}()),this); diff --git a/dist/flexsearch.light.js b/dist/flexsearch.light.js new file mode 100644 index 0000000..8579896 --- /dev/null +++ b/dist/flexsearch.light.js @@ -0,0 +1,18 @@ +/* + FlexSearch v0.3.51 + Copyright 2019 Nextapps GmbH + Author: Thomas Wilkerling + Released under the Apache 2.0 Licence + https://github.com/nextapps-de/flexsearch +*/ +'use strict';(function(e,u,v){let m;(m=v.define)&&m.amd?m([],function(){return u}):(m=v.modules)?m[e.toLowerCase()]=u:"object"===typeof exports?module.exports=u:v[e]=u})("FlexSearch",function(){function e(a){a||(a=x);this.id=a.id||G++;this.init(a);u(this,"index",function(){return this.a});u(this,"length",function(){return Object.keys(this.a).length})}function u(a,b,c){Object.defineProperty(a,b,{get:c})}function v(a,b){for(let c=0;c=g&&(a=a[9-(d+.5>>0)],a=a[c]||(a[c]=[]),a[a.length]=f);return d}function z(a,b){if(a){const c=Object.keys(a);for(let f=0,d=c.length;fa?1:a?-1:0}function I(a,b){a=a.length-b.length;return 0>a?-1:a?1:0}function y(a){return"function"===typeof a} +function A(a){return"undefined"===typeof a}function C(a){const b=Array(a);for(let c=0;ch;c--)l=n.substring(h,c),m(q,f,l,a,b,k,d)}break;default:if(g=m(q,f,n,a,1,k,d),r&&1=d)for(g=f._ctx[n]||(f._ctx[n]=t()),n=this.c[n]||(this.c[n]=C(10-(d||0))),k=e-r,l=e+r+1,0>k&&(k=0),l>p&&(l=p);kb&&(g=g.slice(0,b)));e=g}return e};e.prototype.clear=function(){return this.destroy().init()};e.prototype.destroy=function(){this.g=this.c=this.a=null;return this};const w={icase:function(a){return a.toLowerCase()}}; +return e}(!1),this); diff --git a/dist/flexsearch.min.js b/dist/flexsearch.min.js new file mode 100644 index 0000000..f123fca --- /dev/null +++ b/dist/flexsearch.min.js @@ -0,0 +1,30 @@ +/* + FlexSearch v0.3.51 + Copyright 2019 Nextapps GmbH + Author: Thomas Wilkerling + Released under the Apache 2.0 Licence + https://github.com/nextapps-de/flexsearch +*/ +'use strict';(function(u,z,h){let v;(v=h.define)&&v.amd?v([],function(){return z}):(v=h.modules)?v[u.toLowerCase()]=z:"object"===typeof exports?module.exports=z:h[u]=z})("FlexSearch",function P(u){function h(b){D(b)&&(b=J[b]);b||(b=w);this.id=b.id||Q++;this.init(b);A(this,"index",function(){return this.a});A(this,"length",function(){return Object.keys(this.a).length})}function v(b,a,c,d){this.m!==this.c&&(this.g=this.g.concat(c),this.m++,d&&this.g.length>=d&&(this.m=this.c),this.A&&this.m===this.c&& +(this.cache&&this.j.set(a,this.g),this.A(this.g),this.g=[]));return this}function A(b,a,c){Object.defineProperty(b,a,{get:c})}function f(b){return new RegExp(b,"g")}function m(b,a){for(let c=0;c=g&&(b=b[9-(e+.5>>0)],b=b[c]||(b[c]=[]),b[b.length]=d);return e}function H(b,a){if(b){const c=Object.keys(b);for(let d=0,e=c.length;db?1:b?-1:0}function S(b,a){b=b.length-a.length;return 0>b?-1:b? +1:0}function T(b,a,c){let d=[],e;const l=b.length;if(1a&&(d=d.slice(0,a)));return d}function D(b){return"string"===typeof b}function F(b){return"function"===typeof b}function x(b){return"undefined"===typeof b}function L(b){const a=Array(b);for(let c=0;c=this.i.length&&(this.w=0),this.i[this.w].postMessage({add:!0,id:b,content:a}),this.a[f]=""+this.w,c&&c(),this;if(!e){if(this.async&&"function"!==typeof importScripts){let e= +this;f=new Promise(function(c){setTimeout(function(){e.add(b,a,null,d,!0);e=null;c()})});if(c)f.then(c);else return f;return this}if(c)return this.add(b,a,null,d,!0),c(),this}a=this.encode(a);if(!a.length)return this;c=this.b;e=F(c)?c(a):a.split(M);const l=r();l._ctx=r();const q=this.threshold,t=this.depth,E=this.f,m=e.length;for(let a=0;ak;c--)n=g.substring(k,c),C(E,l,n,b,a,p,q)}break;default:if(h=C(E,l,g,b,1,p,q),t&&1=q)for(h=l._ctx[g]||(l._ctx[g]=r()),g=this.h[g]||(this.h[g]=L(10-(q||0))),p=a-t,n=a+t+1,0>p&&(p=0),n>m&&(n=m);pc;d--)e= +f[d-1],f[d]=e,b[e]=d;f[c]=a;b[a]=c}}}return b};return b}();return h}(function(){const u={},z="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(h,v,A,f,m){A=z?URL.createObjectURL(new Blob(["("+A.toString()+")()"],{type:"text/javascript"})):h+".min.js";h+="-"+v;u[h]||(u[h]=[]);u[h][m]=new Worker(A);u[h][m].onmessage=f;return u[h][m]}}()),this); diff --git a/dist/flexsearch.node.js b/dist/flexsearch.node.js new file mode 100644 index 0000000..73535b5 --- /dev/null +++ b/dist/flexsearch.node.js @@ -0,0 +1,26 @@ +/* + FlexSearch v0.3.51 + Copyright 2019 Nextapps GmbH + Author: Thomas Wilkerling + Released under the Apache 2.0 Licence + https://github.com/nextapps-de/flexsearch +*/ +'use strict';(function(g,x,d){let m;(m=d.define)&&m.amd?m([],function(){return x}):(m=d.modules)?m[g.toLowerCase()]=x:"object"===typeof exports?module.exports=x:d[g]=x})("FlexSearch",function(){function g(b){B(b)&&(b=G[b]);b||(b=w);this.id=b.id||L++;this.init(b);x(this,"index",function(){return this.b});x(this,"length",function(){return Object.keys(this.b).length})}function x(b,a,c){Object.defineProperty(b,a,{get:c})}function d(b){return new RegExp(b,"g")}function m(b,a){for(let c=0;c=h&&(b=b[9-(e+.5>>0)],b=b[c]||(b[c]=[]),b[b.length]=f);return e}function E(b,a){if(b){const c=Object.keys(b);for(let f=0,e=c.length;fb?1:b?-1:0}function N(b,a){b=b.length-a.length;return 0>b?-1:b?1:0}function O(b,a,c){let f=[],e;const d=b.length;if(1a&&(f=f.slice(0,a)));return f}function B(b){return"string"===typeof b}function C(b){return"function"===typeof b}function y(b){return"undefined"===typeof b}function H(b){const a= +Array(b);for(let c=0;ck;c--)q=h.substring(k,c),A(m,n,q,b,a,l,p)}break;default:if(g=A(m,n,h,b,1,l,p),u&&1=p)for(g=n._ctx[h]||(n._ctx[h]=t()),h=this.f[h]||(this.f[h]=H(10-(p||0))),l=a-u,q=a+u+1,0>l&&(l=0),q>v&&(q=v);lc;d--)e=f[d-1],f[d]=e,b[e]=d;f[c]=a;b[a]=c}}}return b};return b}();return g}(!1),this); diff --git a/flexsearch.compact.js b/flexsearch.compact.js deleted file mode 100644 index 40f79e8..0000000 --- a/flexsearch.compact.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - FlexSearch v0.3.5 - Copyright 2019 Nextapps GmbH - Author: Thomas Wilkerling - Released under the Apache 2.0 Licence - https://github.com/nextapps-de/flexsearch -*/ -'use strict';(function(f,r,d){let h;(h=d.define)&&h.amd?h([],function(){return r}):(h=d.modules)?h[f.toLowerCase()]=r:"object"===typeof exports?module.exports=r:d[f]=r})("FlexSearch",function(){function f(a){z(a)&&(a=F[a]);a||(a=v);this.id=a.id||L++;this.init(a);r(this,"index",function(){return this.b});r(this,"length",function(){return Object.keys(this.b).length})}function r(a,b,c){Object.defineProperty(a,b,{get:c})}function d(a){return new RegExp(a,"g")}function h(a,b){for(let c=0;c=m&&(a=a[9-(e+.5>>0)],a=a[c]||(a[c]=[]),a[a.length]=g);return e}function C(a,b){if(a){const c=Object.keys(a);for(let g=0,d=c.length;ga?1:a?-1:0}function N(a,b){a=a.length-b.length;return 0>a?-1:a?1:0}function O(a,b,c){let d=[],e;const u=a.length;if(1b&&(d=d.slice(0,b)));return d}function z(a){return"string"===typeof a}function A(a){return"function"===typeof a}function B(a){return"undefined"===typeof a}function H(a){const b= -Array(a);for(let c=0;ck;c--)n=m.substring(k,c),y(u,h,n,a,b,l,p)}break;default:if(f=y(u,h,m,a,1,l,p),q&&1=p)for(f=h._ctx[m]||(h._ctx[m]=t()),m=this.c[m]||(this.c[m]=H(10-(p||0))),l=b-q,n=b+q+1,0>l&&(l= -0),n>w&&(n=w);l} */ - const index_blacklist = (function(){ - - const array = Object.getOwnPropertyNames(/** @type {!Array} */ (({}).__proto__)); - const map = create_object(); - - for(let i = 0; i < array.length; i++){ - - map[array[i]] = 1; - } - - return map; - })(); + // const index_blacklist = (function(){ + // + // const array = Object.getOwnPropertyNames(/** @type {!Array} */ (({}).__proto__)); + // const map = create_object(); + // + // for(let i = 0; i < array.length; i++){ + // + // map[array[i]] = 1; + // } + // + // return map; + // }()); /** * @param {string|Object=} options @@ -213,7 +215,7 @@ FlexSearch.registerMatcher = function(matcher){ - for(let key in matcher){ + for(const key in matcher){ if(matcher.hasOwnProperty(key)){ @@ -279,6 +281,35 @@ // } }; + function worker_handler(id, query, result, limit){ + + if(this._task_completed !== this.worker){ + + this._task_result = this._task_result.concat(result); + this._task_completed++; + + // TODO: sort results, return array of relevance [0...9] and apply in main thread + + if(limit && (this._task_result.length >= limit)){ + + this._task_completed = this.worker; + } + + if(this._current_callback && (this._task_completed === this.worker)){ + + if(this.cache){ + + this._cache.set(query, this._task_result); + } + + this._current_callback(this._task_result); + this._task_result = []; + } + } + + return this; + } + /** * @param {Object=} options * @export @@ -291,10 +322,10 @@ options || (options = defaults); - let custom = /** @type {?string} */ (options["profile"]); - const profile = SUPPORT_PRESETS && custom ? presets[custom] : {}; + let custom = /** @type {?string} */ (options["preset"]); + const preset = SUPPORT_PRESETS && custom ? presets[custom] : {}; - if(DEBUG && !profile){ + if(DEBUG && !preset){ console.warn("Preset not found: " + custom); } @@ -303,66 +334,36 @@ if(SUPPORT_WORKER && (custom = options["worker"])){ - if(typeof Worker !== "undefined"){ - - const self = this; - const threads = parseInt(custom, 10) || 4; - - /** @private */ - self._current_task = -1; - /** @private */ - self._task_completed = 0; - /** @private */ - self._task_result = []; - /** @private */ - self._current_callback = null; - //self._ids_count = new Array(threads); - /** @private */ - self._worker = new Array(threads); - - for(let i = 0; i < threads; i++){ - - //self._ids_count[i] = 0; - - self._worker[i] = addWorker(self.id, i, options /*|| defaults*/, function(id, query, result, limit){ - - if(self._task_completed === self.worker){ - - return; - } - - self._task_result = self._task_result.concat(result); - self._task_completed++; - - // TODO: sort results, return array of relevance [0...9] and apply in main thread - - if(limit && (self._task_result.length >= limit)){ - - self._task_completed = self.worker; - } - - if(self._current_callback && (self._task_completed === self.worker)){ - - if(self.cache){ - - self._cache.set(query, self._task_result); - } - - self._current_callback(self._task_result); - self._task_result = []; - } - - return self; - }); - } - } - else{ + if(typeof Worker === "undefined"){ options["worker"] = false; /** @private */ this._worker = null; } + else{ + + const threads = parseInt(custom, 10) || 4; + + /** @private */ + this._current_task = -1; + /** @private */ + this._task_completed = 0; + /** @private */ + this._task_result = []; + /** @private */ + this._current_callback = null; + //this._ids_count = new Array(threads); + /** @private */ + this._worker = new Array(threads); + + for(let i = 0; i < threads; i++){ + + //this._ids_count[i] = 0; + + this._worker[i] = addWorker(this.id, i, options /*|| defaults*/, worker_handler.bind(this)); + } + } } // apply custom options @@ -371,7 +372,7 @@ this.tokenize = ( options["tokenize"] || - profile.tokenize || + preset.tokenize || this.tokenize || defaults.tokenize ); @@ -401,7 +402,7 @@ is_undefined(custom = options["threshold"]) ? - profile.threshold || + preset.threshold || this.threshold || defaults.threshold : @@ -413,7 +414,7 @@ is_undefined(custom = options["depth"]) ? - profile.depth || + preset.depth || this.depth || defaults.depth : @@ -436,7 +437,7 @@ custom = is_undefined(custom = options["encode"]) ? - profile.encode + preset.encode : custom; @@ -685,7 +686,8 @@ return this; } - else if(callback){ + + if(callback){ this.add(id, content, null, _skip_update, true); callback(); @@ -974,7 +976,8 @@ return this; } - else if(callback){ + + if(callback){ this.remove(id, null, true); callback(); @@ -1113,7 +1116,8 @@ return this; } - else if(callback){ + + if(callback){ callback(this.search(_query, limit, null, true)); @@ -1138,15 +1142,7 @@ // invalidate cache - if(!this._cache_status){ - - this._cache.clear(); - this._cache_status = true; - } - - // validate cache - - else { + if(this._cache_status){ const cache = this._cache.get(query); @@ -1155,6 +1151,14 @@ return cache; } } + + // validate cache + + else { + + this._cache.clear(); + this._cache_status = true; + } } // encode string @@ -1263,13 +1267,10 @@ //check[check.length] = map_check; } - else{ + else if(!SUPPORT_SUGGESTIONS || !this.suggest){ - if(!SUPPORT_SUGGESTIONS || !this.suggest){ - - found = false; - break; - } + found = false; + break; } check_words[value] = 1; @@ -1452,8 +1453,8 @@ const regex_whitespace = regex("\\s+"), regex_strip = regex("[^a-z0-9 ]"), - regex_space = regex("[-/]"), - regex_vowel = regex("[aeiouy]"); + regex_space = regex("[-/]"); + //regex_vowel = regex("[aeiouy]"); /** @const {Array} */ const regex_pairs = [ @@ -1471,7 +1472,7 @@ replace(value.toLowerCase(), regex_pairs) ); }; - })(); + }()); /** @const */ @@ -1535,7 +1536,7 @@ return ( - str !== " " ? str : "" + str === " " ? "" : str ); }; }()), @@ -1544,7 +1545,7 @@ "advanced": (function(){ - const regex_space = regex(" "), + const //regex_space = regex(" "), regex_ae = regex("ae"), regex_ai = regex("ai"), regex_ay = regex("ay"), @@ -1600,7 +1601,7 @@ // normalize special pairs if(string.length > 2){ - string = replace(string, regex_pairs) + string = replace(string, regex_pairs); } if(!_skip_post_processing){ @@ -1618,7 +1619,7 @@ return string; }; - })(), + }()), // phonetic transformation @@ -1680,7 +1681,7 @@ return str; }; - })(), + }()), "balance": global_encoder_balance @@ -1712,14 +1713,14 @@ ); }; - })() : null; + }()) : null; */ // Flexi-Cache const Cache = SUPPORT_CACHE ? (function(){ - function Cache(limit){ + function CacheClass(limit){ this.clear(); @@ -1727,7 +1728,7 @@ this.limit = (limit !== true) && limit; } - Cache.prototype.clear = function(){ + CacheClass.prototype.clear = function(){ /** @private */ this.cache = create_object(); @@ -1739,7 +1740,7 @@ this.ids = []; }; - Cache.prototype.set = function(key, value){ + CacheClass.prototype.set = function(key, value){ if(this.limit && is_undefined(this.cache[key])){ @@ -1775,7 +1776,7 @@ * Note: It is better to have the complexity when fetching the cache: */ - Cache.prototype.get = function(key){ + CacheClass.prototype.get = function(key){ const cache = this.cache[key]; @@ -1807,10 +1808,10 @@ // copy values from predecessors for(let i = old_index; i > current_index; i--) { - const key = ids[i - 1]; + const tmp = ids[i - 1]; - ids[i] = key; - index[key] = i; + ids[i] = tmp; + index[tmp] = i; } // push new value on top @@ -1823,9 +1824,9 @@ return cache; }; - return Cache; + return CacheClass; - })() : null; + }()) : null; if(PROFILER){ @@ -1885,17 +1886,17 @@ /** * @param {!string} str - * @param {RegExp|Array} regex + * @param {RegExp|Array} regexp * @returns {string} */ - function replace(str, regex/*, replacement*/){ + function replace(str, regexp/*, replacement*/){ //if(is_undefined(replacement)){ - for(let i = 0; i < /** @type {Array} */ (regex).length; i += 2){ + for(let i = 0; i < /** @type {Array} */ (regexp).length; i += 2){ - str = str.replace(regex[i], regex[i + 1]); + str = str.replace(regexp[i], regexp[i + 1]); } return str; @@ -1929,29 +1930,27 @@ return dupes[value]; } - else{ - const score = ( + const score = ( - partial_score ? + partial_score ? - ((9 - (threshold || 6)) * context_score) + ((threshold || 6) * partial_score) - : - context_score - ); + ((9 - (threshold || 6)) * context_score) + ((threshold || 6) * partial_score) + : + context_score + ); - dupes[value] = score; + dupes[value] = score; - if(score >= threshold){ + if(score >= threshold){ - let arr = map[9 - ((score + 0.5) >> 0)]; - arr = arr[value] || (arr[value] = []); + let arr = map[9 - ((score + 0.5) >> 0)]; + arr = arr[value] || (arr[value] = []); - arr[arr.length] = id; - } - - return score; + arr[arr.length] = id; } + + return score; } /** @@ -2179,20 +2178,20 @@ } /** - * @param {Object} stemmer + * @param {Object} stem * @param encoder * @returns {Array} */ - function init_stemmer(stemmer, encoder){ + function init_stemmer(stem, encoder){ const final = []; - if(stemmer){ + if(stem){ - for(const key in stemmer){ + for(const key in stem){ - if(stemmer.hasOwnProperty(key)){ + if(stem.hasOwnProperty(key)){ const tmp = encoder ? encoder(key) : key; @@ -2202,9 +2201,9 @@ encoder ? - encoder(stemmer[key]) + encoder(stem[key]) : - stemmer[key] + stem[key] ); } } @@ -2377,7 +2376,7 @@ if(tmp){ - for(let i = 0, len = tmp.length; i < len; i++){ + for(i = 0, length = tmp.length; i < length; i++){ result[count++] = tmp[i]; @@ -2745,6 +2744,93 @@ return Object.create(null); } + function worker_module(){ + + let id; + + /** @type {FlexSearch} */ + let FlexSearchWorker; + + /** @lends {Worker} */ + self.onmessage = function(event){ + + const data = event["data"]; + + if(data){ + + if(data["search"]){ + + const results = FlexSearchWorker["search"](data["content"], + + data["threshold"] ? + + { + "limit": data["limit"], + "threshold": data["threshold"] + } + : + data["limit"] + ); + + /** @lends {Worker} */ + self.postMessage({ + + "id": id, + "content": data["content"], + "limit": data["limit"], + "result": results + }); + } + else if(data["add"]){ + + FlexSearchWorker["add"](data["id"], data["content"]); + } + else if(data["update"]){ + + FlexSearchWorker["update"](data["id"], data["content"]); + } + else if(data["remove"]){ + + FlexSearchWorker["remove"](data["id"]); + } + else if(data["clear"]){ + + FlexSearchWorker["clear"](); + } + else if(SUPPORT_INFO && data["info"]){ + + const info = FlexSearchWorker["info"](); + + info["worker"] = id; + + console.log(info); + + /** @lends {Worker} */ + //self.postMessage(info); + } + else if(data["register"]){ + + id = data["id"]; + + data["options"]["cache"] = false; + data["options"]["async"] = false; + data["options"]["worker"] = false; + + FlexSearchWorker = new Function( + + data["register"].substring( + + data["register"].indexOf("{") + 1, + data["register"].lastIndexOf("}") + ) + )(); + + FlexSearchWorker = new FlexSearchWorker(data["options"]); + } + } + }; + } + function addWorker(id, core, options, callback){ const thread = register_worker( @@ -2756,92 +2842,7 @@ "id" + id, // worker: - function(){ - - let id; - - /** @type {FlexSearch} */ - let FlexSearchWorker; - - /** @lends {Worker} */ - self.onmessage = function(event){ - - const data = event["data"]; - - if(data){ - - if(data["search"]){ - - const results = FlexSearchWorker["search"](data["content"], - - data["threshold"] ? - - { - "limit": data["limit"], - "threshold": data["threshold"] - } - : - data["limit"] - ); - - /** @lends {Worker} */ - self.postMessage({ - - "id": id, - "content": data["content"], - "limit": data["limit"], - "result": results - }); - } - else if(data["add"]){ - - FlexSearchWorker["add"](data["id"], data["content"]); - } - else if(data["update"]){ - - FlexSearchWorker["update"](data["id"], data["content"]); - } - else if(data["remove"]){ - - FlexSearchWorker["remove"](data["id"]); - } - else if(data["clear"]){ - - FlexSearchWorker["clear"](); - } - else if(SUPPORT_INFO && data["info"]){ - - const info = FlexSearchWorker["info"](); - - info["worker"] = id; - - console.log(info); - - /** @lends {Worker} */ - //self.postMessage(info); - } - else if(data["register"]){ - - id = data["id"]; - - data["options"]["cache"] = false; - data["options"]["async"] = false; - data["options"]["worker"] = false; - - FlexSearchWorker = new Function( - - data["register"].substring( - - data["register"].indexOf("{") + 1, - data["register"].lastIndexOf("}") - ) - )(); - - FlexSearchWorker = new FlexSearchWorker(data["options"]); - } - } - }; - }, + worker_module, // callback: function(event){ diff --git a/flexsearch.light.js b/flexsearch.light.js deleted file mode 100644 index df824cd..0000000 --- a/flexsearch.light.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - FlexSearch v0.3.5 - Copyright 2019 Nextapps GmbH - Author: Thomas Wilkerling - Released under the Apache 2.0 Licence - https://github.com/nextapps-de/flexsearch -*/ -'use strict';(function(e,u,v){let m;(m=v.define)&&m.amd?m([],function(){return u}):(m=v.modules)?m[e.toLowerCase()]=u:"object"===typeof exports?module.exports=u:v[e]=u})("FlexSearch",function(){function e(a){a||(a=x);this.id=a.id||G++;this.init(a);u(this,"index",function(){return this.a});u(this,"length",function(){return Object.keys(this.a).length})}function u(a,b,c){Object.defineProperty(a,b,{get:c})}function v(a,b){for(let c=0;c=g&&(a=a[9-(d+.5>>0)],a=a[c]||(a[c]=[]),a[a.length]=f);return d}function z(a,b){if(a){const c=Object.keys(a);for(let f=0,d=c.length;fa?1:a?-1:0}function I(a,b){a=a.length-b.length;return 0>a?-1:a?1:0}function y(a){return"function"===typeof a} -function A(a){return"undefined"===typeof a}function C(a){const b=Array(a);for(let c=0;ch;c--)l=n.substring(h,c),m(q,f,l,a,b,k,d)}break;default:if(g=m(q,f,n,a,1,k,d),t&&1=d)for(g=f._ctx[n]||(f._ctx[n]=r()),n=this.c[n]||(this.c[n]=C(10-(d|| -0))),k=e-t,l=e+t+1,0>k&&(k=0),l>p&&(l=p);kb&&(g=g.slice(0,b)));e=g}return e};e.prototype.clear=function(){return this.destroy().init()}; -e.prototype.destroy=function(){this.g=this.c=this.a=null;return this};const w={icase:function(a){return a.toLowerCase()}};return e}(!1),this); diff --git a/flexsearch.min.js b/flexsearch.min.js deleted file mode 100644 index f74dc17..0000000 --- a/flexsearch.min.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - FlexSearch v0.3.5 - Copyright 2019 Nextapps GmbH - Author: Thomas Wilkerling - Released under the Apache 2.0 Licence - https://github.com/nextapps-de/flexsearch -*/ -'use strict';(function(u,B,g){let v;(v=g.define)&&v.amd?v([],function(){return B}):(v=g.modules)?v[u.toLowerCase()]=B:"object"===typeof exports?module.exports=B:g[u]=B})("FlexSearch",function O(u){function g(a){E(a)&&(a=J[a]);a||(a=w);this.id=a.id||P++;this.init(a);v(this,"index",function(){return this.a});v(this,"length",function(){return Object.keys(this.a).length})}function v(a,b,c){Object.defineProperty(a,b,{get:c})}function e(a){return new RegExp(a,"g")}function x(a,b){for(let c=0;c=h&&(a=a[9-(f+.5>>0)],a=a[c]||(a[c]=[]),a[a.length]=d);return f}function H(a,b){if(a){const c=Object.keys(a);for(let d=0,f=c.length;da?1:a?-1:0}function T(a,b){a=a.length-b.length;return 0>a?-1:a?1:0}function U(a,b,c){let d=[],f;const l=a.length;if(1b&&(d=d.slice(0,b)));return d}function E(a){return"string"===typeof a}function F(a){return"function"===typeof a}function A(a){return"undefined"===typeof a}function K(a){const b=Array(a);for(let c=0;c=f&&(c.o=c.c),c.B&&c.o===c.c&&(c.cache&&c.j.set(b,c.h),c.B(c.h),c.h=[]),c})}else a.worker=!1,this.i=null;this.b=a.tokenize||c.b||this.b||w.b;this.async="undefined"===typeof Promise||A(b=a.async)?this.async|| -w.async:b;this.c=A(b=a.worker)?this.c||w.c:b;this.threshold=A(b=a.threshold)?c.threshold||this.threshold||w.threshold:b;this.depth=A(b=a.depth)?c.depth||this.depth||w.depth:b;this.u=A(b=a.suggest)?this.u||w.u:b;this.s=(b=A(b=a.encode)?c.encode:b)&&D[b]&&D[b].bind(D)||(F(b)?b:this.s||!1);(b=a.matcher)&&this.addMatcher(b);if(b=a.filter)this.filter=Q(M[b]||b,this.s);if(b=a.stemmer)this.stemmer=R(N[b]||b,this.s);this.f=K(10-(this.threshold||0));this.g=r();this.a=r();this.v=!0;this.j=(this.cache=b=A(b= -a.cache)?this.cache||w.cache:b)?new W(b):!1;return this};g.prototype.encode=function(a){a&&G.length&&(a=x(a,G));a&&this.m.length&&(a=x(a,this.m));a&&this.s&&(a=this.s(a));a&&this.stemmer&&(a=x(a,this.stemmer));return a};g.prototype.addMatcher=function(a){const b=this.m;for(const c in a)a.hasOwnProperty(c)&&b.push(e(c),a[c]);return this};g.prototype.add=function(a,b,c,d,f){if(b&&E(b)&&(a||0===a)){var e="@"+a;if(this.a[e]&&!d)return this.update(a,b);if(this.c)return++this.w>=this.i.length&&(this.w= -0),this.i[this.w].postMessage({add:!0,id:a,content:b}),this.a[e]=""+this.w,c&&c(),this;if(!f){if(this.async&&"function"!==typeof importScripts){let f=this;e=new Promise(function(c){setTimeout(function(){f.add(a,b,null,d,!0);f=null;c()})});if(c)e.then(c);else return e;return this}if(c)return this.add(a,b,null,d,!0),c(),this}b=this.encode(b);if(!b.length)return this;c=this.b;f=F(c)?c(b):b.split(L);const l=r();l._ctx=r();const p=this.threshold,t=this.depth,z=this.f,C=f.length;for(let b=0;bk;c--)n=h.substring(k,c),y(z,l,n,a,b,m,p)}break;default:if(g=y(z,l,h,a,1,m,p),t&&1=p)for(g=l._ctx[h]||(l._ctx[h]=r()),h=this.g[h]||(this.g[h]=K(10-(p||0))),m=b-t,n=b+t+1,0>m&&(m=0),n>C&&(n=C);mc;d--)f=e[d-1],e[d]=f,b[f]=d;e[c]=a;b[a]=c}}}return b};return a}();return g}(function(){const u={},B="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(g,v,e,x,y){e=B?URL.createObjectURL(new Blob(["("+e.toString()+")()"],{type:"text/javascript"})):g+".min.js";g+="-"+v;u[g]||(u[g]=[]);u[g][y]=new Worker(e);u[g][y].onmessage=x;return u[g][y]}}()), -this); diff --git a/package.json b/package.json index 11f8519..7d80816 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "flexsearch", - "version": "0.3.5", + "version": "0.3.51", "description": "Next-Generation full text search library with zero dependencies.", "homepage": "https://github.com/nextapps-de/flexsearch/", "author": "Thomas Wilkerling", @@ -17,7 +17,8 @@ "url": "https://github.com/nextapps-de/flexsearch/issues", "email": "info@nextapps.de" }, - "main": "flexsearch.min.js", + "main": "dist/flexsearch.node.js", + "browser": "dist/flexsearch.min.js", "preferGlobal": false, "bin": {}, "repository": { @@ -30,8 +31,9 @@ "build-compact": "node compile RELEASE=compact DEBUG=false PROFILER=false SUPPORT_WORKER=false SUPPORT_ENCODER=true SUPPORT_CACHE=false SUPPORT_ASYNC=true SUPPORT_PRESETS=true SUPPORT_SUGGESTIONS=false SUPPORT_SERIALIZE=false SUPPORT_INFO=false SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false", "build-custom": "node compile RELEASE=custom DEBUG=false PROFILER=false SUPPORT_WORKER=false SUPPORT_ENCODER=false SUPPORT_CACHE=false SUPPORT_ASYNC=false SUPPORT_PRESETS=false SUPPORT_SUGGESTIONS=false SUPPORT_SERIALIZE=false SUPPORT_INFO=false SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false", "build-es5": "node compile RELEASE=es5 DEBUG=true PROFILER=false SUPPORT_WORKER=true SUPPORT_ENCODER=true SUPPORT_CACHE=true SUPPORT_ASYNC=true SUPPORT_PRESETS=true SUPPORT_SUGGESTIONS=true SUPPORT_SERIALIZE=true SUPPORT_INFO=true SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false LANGUAGE_OUT=ECMASCRIPT5_STRICT", + "build-node": "node compile RELEASE=node DEBUG=false PROFILER=false SUPPORT_WORKER=false SUPPORT_ENCODER=true SUPPORT_CACHE=true SUPPORT_ASYNC=true SUPPORT_PRESETS=true SUPPORT_SUGGESTIONS=true SUPPORT_SERIALIZE=true SUPPORT_INFO=true SUPPORT_LANG_DE=false SUPPORT_LANG_EN=false", "build-lang": "node compile RELEASE=lang", - "build-all": "npm run build && npm run build-light && npm run build-compact && npm run build-es5 && npm run build-lang", + "build-all": "npm run build && npm run build-light && npm run build-compact && npm run build-es5 && npm run build-node && npm run build-lang", "test-production": "nyc --reporter=html --reporter=text mocha --timeout=3000 test --exit", "test-light": "nyc --reporter=html --reporter=text mocha --timeout=3000 test/ --exit", "test-develop": "nyc --reporter=html --reporter=text mocha --timeout=3000 --exit", @@ -42,6 +44,7 @@ }, "files": [ "flexsearch.js", + "dist/", "lang/", "test/", "compile.js", diff --git a/test/benchmark-presets.html b/test/benchmark-presets.html index e26d0c3..581d7de 100644 --- a/test/benchmark-presets.html +++ b/test/benchmark-presets.html @@ -22,7 +22,7 @@

- + + diff --git a/test/flexsearch.es5.js b/test/flexsearch.es5.js deleted file mode 100644 index 26a26c4..0000000 --- a/test/flexsearch.es5.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - FlexSearch v0.3.5 - Copyright 2019 Nextapps GmbH - Author: Thomas Wilkerling - Released under the Apache 2.0 Licence - https://github.com/nextapps-de/flexsearch -*/ -'use strict';function I(g){var k=0;return function(){return k=e&&(b=b[9-(d+.5>>0)],b=b[a]||(b[a]=[]),b[b.length]=f);return d}function G(b,c){if(b)for(var a=Object.keys(b),f=0,d=a.length;fb?1:b?-1:0}function U(b,c){b=b.length-c.length;return 0>b?-1:b?1:0}function V(b,c,a){var f=[],d=b.length;if(1c&&(f=f.slice(0,c)));return f}function E(b){return"string"===typeof b}function C(b){return"function"===typeof b}function w(b){return"undefined"===typeof b}function M(b){for(var c=Array(b),a=0;a=d&&(f.m=f.i),f.w&&f.m===f.i&&(f.cache&&f.j.set(c,f.f),f.w(f.f),f.f=[]),f})}else b.worker=!1,this.g=null;this.h=b.tokenize||a.h||this.h||x.h;this.async="undefined"===typeof Promise||w(c=b.async)?this.async||x.async:c; -this.i=w(c=b.worker)?this.i||x.i:c;this.threshold=w(c=b.threshold)?a.threshold||this.threshold||x.threshold:c;this.depth=w(c=b.depth)?a.depth||this.depth||x.depth:c;this.A=w(c=b.suggest)?this.A||x.A:c;this.o=(c=w(c=b.encode)?a.encode:c)&&B[c]&&B[c].bind(B)||(C(c)?c:this.o||!1);(c=b.matcher)&&this.addMatcher(c);if(c=b.filter)this.filter=D(O[c]||c,this.o);if(c=b.stemmer)this.stemmer=T(P[c]||c,this.o);this.b=M(10-(this.threshold||0));this.c=y();this.a=y();this.u=!0;this.j=(this.cache=c=w(c=b.cache)? -this.cache||x.cache:c)?new aa(c):!1;return this};e.prototype.encode=function(b){b&&F.length&&(b=l(b,F));b&&this.l.length&&(b=l(b,this.l));b&&this.o&&(b=this.o(b));b&&this.stemmer&&(b=l(b,this.stemmer));return b};e.prototype.addMatcher=function(b){var c=this.l,d;for(d in b)b.hasOwnProperty(d)&&c.push(a(d),b[d]);return this};e.prototype.add=function(b,c,a,f,e){if(c&&E(c)&&(b||0===b)){var g="@"+b;if(this.a[g]&&!f)return this.update(b,c);if(this.i)return++this.v>=this.g.length&&(this.v=0),this.g[this.v].postMessage({add:!0, -id:b,content:c}),this.a[g]=""+this.v,a&&a(),this;if(!e){if(this.async&&"function"!==typeof importScripts){var z=this;g=new Promise(function(a){setTimeout(function(){z.add(b,c,null,f,!0);z=null;a()})});if(a)g.then(a);else return g;return this}if(a)return this.add(b,c,null,f,!0),a(),this}c=this.encode(c);if(!c.length)return this;a=this.h;e=C(a)?a(c):c.split(N);var h=y();h._ctx=y();for(var l=this.threshold,H=this.depth,q=this.b,t=e.length,r=0;rv;w--)p=u.substring(v,w),d(q,h,p,b,x,m,l);break;default:if(n=d(q,h,u,b,1,m,l),H&&1=l)for(n=h._ctx[u]||(h._ctx[u]=y()),u=this.c[u]||(this.c[u]=M(10-(l||0))),m=r-H,p=r+H+1,0>m&&(m=0),p>t&&(p=t);me;c--)h=g[c-1],g[c]=h,d[h]= -c;g[e]=a;d[a]=e}}}return b};return a}();return e}(function(){var g={},k="undefined"!==typeof Blob&&"undefined"!==typeof URL&&URL.createObjectURL;return function(e,h,a,l,d){a=k?URL.createObjectURL(new Blob(["("+a.toString()+")()"],{type:"text/javascript"})):e+".es5.js";e+="-"+h;g[e]||(g[e]=[]);g[e][d]=new Worker(a);g[e][d].onmessage=l;console.log("Register Worker: "+e+"@"+d);return g[e][d]}}()),this); diff --git a/test/index.html b/test/index.html index 4b5288b..9c6b997 100644 --- a/test/index.html +++ b/test/index.html @@ -12,7 +12,7 @@ - + +
diff --git a/test/matching.html b/test/matching.html index d50dccd..17b13b2 100644 --- a/test/matching.html +++ b/test/matching.html @@ -201,7 +201,7 @@
Most relevant results was successfully found in the first place.
Note: Open console and type e.g. data[493] - + diff --git a/test/test.js b/test/test.js index 6e6f2fa..a7d3af4 100644 --- a/test/test.js +++ b/test/test.js @@ -8,7 +8,7 @@ if(typeof module !== "undefined"){ var env = process.argv[3] === "test" ? "min" : process.argv[3] === "test/" ? "light" : ""; var expect = require("chai").expect; - var FlexSearch = require("../flexsearch" + (env ? "." + env : "") + ".js"); + var FlexSearch = require("../" + (env ? "dist/": "") + "flexsearch" + (env ? "." + env : "") + ".js"); } var flexsearch_default;