Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

minisearch

Package Overview
Dependencies
Maintainers
1
Versions
81
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

minisearch - npm Package Compare versions

Comparing version 0.1.6 to 0.1.7

CONTRIBUTING.md

3

.esdoc.json

@@ -20,2 +20,5 @@ {

"author": "https://twitter.com/lucaongaro"
},
"manual": {
"files": ["README.md", "CONTRIBUTING.md"]
}

@@ -22,0 +25,0 @@ }

2

dist/minisearch.js

@@ -1,1 +0,1 @@

!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("minisearch",[],t):"object"==typeof exports?exports.minisearch=t():e.minisearch=t()}("undefined"!=typeof self?self:this,function(){return function(e){var t={};function n(i){if(t[i])return t[i].exports;var s=t[i]={i:i,l:!1,exports:{}};return e[i].call(s.exports,s,s.exports,n),s.l=!0,s.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var s in e)n.d(i,s,function(t){return e[t]}.bind(null,s));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);class i{constructor(e,t=s){const n=e._tree,i=Object.keys(n);this.set=e,this.type=t,this.path=i.length>0?[{node:n,keys:i}]:[]}next(){const e=this.dive();return this.backtrack(),e}dive(){if(0===this.path.length)return{done:!0};const{node:e,keys:t}=u(this.path);return u(t)===c?{done:!1,value:this.result()}:(this.path.push({node:e[u(t)],keys:Object.keys(e[u(t)])}),this.dive())}backtrack(){0!==this.path.length&&(u(this.path).keys.pop(),u(this.path).keys.length>0||(this.path.pop(),this.backtrack()))}key(){return this.set._prefix+this.path.map(({keys:e})=>u(e)).filter(e=>e!==c).join("")}value(){return u(this.path).node[c]}result(){return this.type===o?this.value():this.type===r?this.key():[this.key(),this.value()]}[Symbol.iterator](){return this}}const s="ENTRIES",r="KEYS",o="VALUES",c="",u=function(e){return e[e.length-1]},d=function(e,t,n,i=0,s=h){const r=[{distance:0,ia:i,ib:0,edit:s}],o=[],c=[];for(;r.length>0;){const{distance:i,ia:s,ib:u,edit:d}=r.pop();if(o[s]=o[s]||[],!(o[s][u]&&o[s][u]<=i))if(o[s][u]=i,u!==t.length)if(e[s]===t[u])r.push({distance:i,ia:s+1,ib:u+1,edit:h});else{if(i>=n)continue;d!==f&&r.push({distance:i+1,ia:s,ib:u+1,edit:a}),s<e.length&&(d!==a&&r.push({distance:i+1,ia:s+1,ib:u,edit:f}),d!==a&&d!==f&&r.push({distance:i+1,ia:s+1,ib:u+1,edit:l}))}else c.push({distance:i,i:s,edit:d})}return c},h=0,l=1,f=2,a=3;var p=function(e,t,n){const i=[{distance:0,i:0,key:"",node:e}],s={};for(;i.length>0;){const{node:e,distance:r,key:o,i:u,edit:h}=i.pop();Object.keys(e).forEach(l=>{if(l===c){const i=r+(t.length-u),[,c]=s[o]||[null,1/0];i<=n&&i<c&&(s[o]=[e[l],i])}else d(t,l,n-r,u,h).forEach(({distance:t,i:n,edit:s})=>{i.push({node:e[l],distance:r+t,key:o+l,i:n,edit:s})})})}return s};class m{constructor(e={},t=""){this._tree=e,this._prefix=t}atPrefix(e){if(!e.startsWith(this._prefix))throw new Error("Mismatched prefix");const[t,n]=_(this._tree,e.slice(this._prefix.length));if(void 0===t){const[t,i]=k(n),s=Object.keys(t).find(e=>e!==c&&e.startsWith(i));if(void 0!==s)return new m({[s.slice(i.length)]:t[s]},e)}return new m(t||{},e)}clear(){delete this._size,this._tree={}}delete(e){return delete this._size,v(this._tree,e)}entries(){return new i(this,s)}forEach(e){for(let[t,n]of this)e(t,n,this)}fuzzyGet(e,t){return p(this._tree,e,t)}get(e){const t=y(this._tree,e);return void 0!==t?t[c]:void 0}has(e){const t=y(this._tree,e);return void 0!==t&&t.hasOwnProperty(c)}keys(){return new i(this,r)}set(e,t){if("string"!=typeof e)throw new Error("key must be a string");return delete this._size,b(this._tree,e)[c]=t,this}get size(){return this._size?this._size:(this._size=0,this.forEach(()=>{this._size+=1}),this._size)}update(e,t){if("string"!=typeof e)throw new Error("key must be a string");delete this._size;const n=b(this._tree,e);return n[c]=t(n[c]),this}values(){return new i(this,o)}[Symbol.iterator](){return this.entries()}}m.from=function(e){const t=new m;for(let[n,i]of e)t.set(n,i);return t},m.fromObject=function(e){return m.from(Object.entries(e))};const _=function(e,t,n=[]){if(0===t.length)return[e,n];const i=Object.keys(e).find(e=>e!==c&&t.startsWith(e));return void 0===i?_(void 0,"",[...n,[e,t]]):_(e[i],t.slice(i.length),[...n,[e,i]])},y=function(e,t){if(0===t.length)return e;const n=Object.keys(e).find(e=>e!==c&&t.startsWith(e));return void 0!==n?y(e[n],t.slice(n.length)):void 0},b=function(e,t){if(0===t.length)return e;const n=Object.keys(e).find(e=>e!==c&&t.startsWith(e));if(void 0===n){const n=Object.keys(e).find(e=>e!==c&&e.startsWith(t[0]));if(void 0!==n){const i=g(t,n);return e[i]={[n.slice(i.length)]:e[n]},delete e[n],b(e[i],t.slice(i.length))}return e[t]={},e[t]}return b(e[n],t.slice(n.length))},g=function(e,t,n=0,i=Math.min(e.length,t.length),s=""){return n>=i?s:e[n]!==t[n]?s:g(e,t,n+1,i,s+e[n])},v=function(e,t){const[n,i]=_(e,t);if(void 0===n)return;delete n[c];const s=Object.keys(n);0===s.length&&O(i),1===s.length&&x(i,s[0],n[s[0]])},O=function(e){if(0===e.length)return;const[t,n]=k(e);delete t[n],0===Object.keys(t).length&&O(e.slice(0,-1))},x=function(e,t,n){if(0===e.length)return;const[i,s]=k(e);i[s+t]=n,delete i[s]},k=function(e){return e[e.length-1]};var j=m;const w="or";class z{constructor(e={}){this._options={...J,...e},this._options.searchOptions={...D,...this._options.searchOptions||{}};const{fields:t}=this._options;if(null==t)throw new Error('Option "fields" must be provided');this._index=new j,this._documentCount=0,this._documentIds={},this._fieldIds={},M(this,t)}add(e){const{tokenize:t,processTerm:n,fields:i,idField:s}=this._options;if(null==e[s])throw new Error(`Document does not have ID field "${s}"`);const r=C(this,e[s]);i.filter(t=>null!=e[t]).forEach(i=>{t(e[i]).forEach(e=>{E(this,this._fieldIds[i],r,n(e))})})}addAll(e){e.forEach(e=>this.add(e))}remove(e){const{tokenize:t,processTerm:n,fields:i,idField:s}=this._options;if(null==e[s])throw new Error(`Document does not have ID field "${s}"`);const[r]=Object.entries(this._documentIds).find(([t,n])=>e[s]===n)||[];if(null==r)throw new Error(`Cannot remove document with ID ${e[s]}: it is not in the index`);i.filter(t=>null!=e[t]).forEach(i=>{t(e[i]).forEach(e=>{I(this,this._fieldIds[i],r,n(e))})}),this._documentCount-=1}search(e,t={}){const{tokenize:n,processTerm:i,searchOptions:s}=this._options;t={...s,...t};const r=n(e).map(i).map(t.termToQuery).map(e=>this.executeQuery(e,t)),o=this.combineResults(r,t.combineWith);return Object.entries(o).map(([e,{score:t,match:n}])=>({id:this._documentIds[e],score:t,match:n})).sort(({score:e},{score:t})=>e<t?1:-1)}get documentCount(){return this._documentCount}executeQuery(e,t={}){const n=((t={...this._options.defaultSearchOptions,...t}).fields||this._options.fields).reduce((e,t)=>({...e,[t]:e[t]||1}),t.boost||{});if(!e.fuzzy&&!e.prefix)return T(this,e.term,n,this._index.get(e.term));const i=[];if(e.fuzzy){const t=e.fuzzy<1?Math.round(e.term.length*e.fuzzy):e.fuzzy;Object.entries(this._index.fuzzyGet(e.term,t)).forEach(([e,[t,s]])=>{i.push(T(this,e,n,t,s))})}return e.prefix&&this._index.atPrefix(e.term).forEach((t,s)=>{i.push(T(this,t,n,s,t.length-e.term.length))}),i.reduce(W[w],{})}combineResults(e,t=w){if(0===e.length)return{};const n=t.toLowerCase();return e.reduce(W[n],null)}toJSON(){return{index:this._index,documentCount:this._documentCount,documentIds:this._documentIds,fieldIds:this._fieldIds}}toJS(){this.toJSON()}}z.loadJSON=function(e,t={}){return z.loadJS(JSON.parse(e),t)},z.loadJS=function(e,t={}){const{index:{_tree:n,_prefix:i},documentCount:s,documentIds:r,fieldIds:o}=e,c=new z(t);return c._index=new j(n,i),c._documentCount=s,c._documentIds=r,c._fieldIds=o,c},z.SearchableMap=j;const E=function(e,t,n,i){e._index.update(i,e=>{const i=(e=e||{})[t]||{df:0,ds:{}};return null==i.ds[n]&&(i.df+=1),i.ds[n]=(i.ds[n]||0)+1,{...e,[t]:i}})},I=function(e,t,n,i){e._index.has(i)?(e._index.update(i,s=>{const r=s[t];return null==r||null==r.ds[n]?(S(e,n,t,i),s):r.df<=1?(delete s[t],s):(r.df-=1,r.ds[n]<=1?(delete r.ds[n],s):(r.ds[n]-=1,{...s,[t]:r}))}),0===Object.keys(e._index.get(i)).length&&e._index.delete(i)):S(e,n,t,i)},S=function(e,t,n,i){if(null==console||null==console.warn)return;const s=Object.entries(e._fieldIds).find(([e,t])=>t===n)[0];console.warn(`MiniSearch: document with ID ${e._documentIds[t]} has changed before removal: term "${i}" was not present in field "${s}". Removing a document after it has changed can corrupt the index!`)},C=function(e,t){const n=e._documentCount;return e._documentIds[n]=t,e._documentCount+=1,n},M=function(e,t){t.forEach((t,n)=>{e._fieldIds[t]=n})},T=function(e,t,n,i,s=0){return null==i?{}:Object.entries(n).reduce((n,[r,o])=>{const{df:c,ds:u}=i[e._fieldIds[r]]||{ds:{}};return Object.entries(u).forEach(([i,u])=>{const d=o/(1+.333*o*s);n[i]=n[i]||{score:0,match:{}},n[i].match[t]=n[i].match[t]||[],n[i].score+=d*P(u,c,e._documentCount),n[i].match[t].push(r)}),n},{})},W={[w]:function(e,t){return Object.entries(t).reduce((e,[t,{score:n,match:i}])=>(null==e[t]?e[t]={score:n,match:i}:(e[t].score+=n,Object.assign(e[t].match,i)),e),e||{})},and:function(e,t){return null==e?t:Object.entries(t).reduce((t,[n,{score:i,match:s}])=>void 0===e[n]?t:(t[n]=t[n]||{},t[n].score=Math.min(e[n].score,i),t[n].match={...e[n].match,...s},t),{})}},P=function(e,t,n){return e*Math.log(n/t)},J={idField:"id",tokenize:e=>e.split(/\W+/).filter(e=>e.length>1),processTerm:e=>e.toLowerCase()},D={termToQuery:e=>({term:e}),combineWith:w};var $=z;t.default=$}]).default});
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("minisearch",[],t):"object"==typeof exports?exports.minisearch=t():e.minisearch=t()}("undefined"!=typeof self?self:this,function(){return function(e){var t={};function n(i){if(t[i])return t[i].exports;var s=t[i]={i:i,l:!1,exports:{}};return e[i].call(s.exports,s,s.exports,n),s.l=!0,s.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var s in e)n.d(i,s,function(t){return e[t]}.bind(null,s));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t);class i{constructor(e,t=s){const n=e._tree,i=Object.keys(n);this.set=e,this.type=t,this.path=i.length>0?[{node:n,keys:i}]:[]}next(){const e=this.dive();return this.backtrack(),e}dive(){if(0===this.path.length)return{done:!0};const{node:e,keys:t}=u(this.path);return u(t)===c?{done:!1,value:this.result()}:(this.path.push({node:e[u(t)],keys:Object.keys(e[u(t)])}),this.dive())}backtrack(){0!==this.path.length&&(u(this.path).keys.pop(),u(this.path).keys.length>0||(this.path.pop(),this.backtrack()))}key(){return this.set._prefix+this.path.map(({keys:e})=>u(e)).filter(e=>e!==c).join("")}value(){return u(this.path).node[c]}result(){return this.type===o?this.value():this.type===r?this.key():[this.key(),this.value()]}[Symbol.iterator](){return this}}const s="ENTRIES",r="KEYS",o="VALUES",c="",u=function(e){return e[e.length-1]},d=function(e,t,n,i=0,s=h){const r=[{distance:0,ia:i,ib:0,edit:s}],o=[],c=[];for(;r.length>0;){const{distance:i,ia:s,ib:u,edit:d}=r.pop();if(o[s]=o[s]||[],!(o[s][u]&&o[s][u]<=i))if(o[s][u]=i,u!==t.length)if(e[s]===t[u])r.push({distance:i,ia:s+1,ib:u+1,edit:h});else{if(i>=n)continue;d!==l&&r.push({distance:i+1,ia:s,ib:u+1,edit:a}),s<e.length&&(d!==a&&r.push({distance:i+1,ia:s+1,ib:u,edit:l}),d!==a&&d!==l&&r.push({distance:i+1,ia:s+1,ib:u+1,edit:f}))}else c.push({distance:i,i:s,edit:d})}return c},h=0,f=1,l=2,a=3;var p=function(e,t,n){const i=[{distance:0,i:0,key:"",node:e}],s={};for(;i.length>0;){const{node:e,distance:r,key:o,i:u,edit:h}=i.pop();Object.keys(e).forEach(f=>{if(f===c){const i=r+(t.length-u),[,c]=s[o]||[null,1/0];i<=n&&i<c&&(s[o]=[e[f],i])}else d(t,f,n-r,u,h).forEach(({distance:t,i:n,edit:s})=>{i.push({node:e[f],distance:r+t,key:o+f,i:n,edit:s})})})}return s};class m{constructor(e={},t=""){this._tree=e,this._prefix=t}atPrefix(e){if(!e.startsWith(this._prefix))throw new Error("Mismatched prefix");const[t,n]=_(this._tree,e.slice(this._prefix.length));if(void 0===t){const[t,i]=k(n),s=Object.keys(t).find(e=>e!==c&&e.startsWith(i));if(void 0!==s)return new m({[s.slice(i.length)]:t[s]},e)}return new m(t||{},e)}clear(){delete this._size,this._tree={}}delete(e){return delete this._size,x(this._tree,e)}entries(){return new i(this,s)}forEach(e){for(let[t,n]of this)e(t,n,this)}fuzzyGet(e,t){return p(this._tree,e,t)}get(e){const t=y(this._tree,e);return void 0!==t?t[c]:void 0}has(e){const t=y(this._tree,e);return void 0!==t&&t.hasOwnProperty(c)}keys(){return new i(this,r)}set(e,t){if("string"!=typeof e)throw new Error("key must be a string");return delete this._size,b(this._tree,e)[c]=t,this}get size(){return this._size?this._size:(this._size=0,this.forEach(()=>{this._size+=1}),this._size)}update(e,t){if("string"!=typeof e)throw new Error("key must be a string");delete this._size;const n=b(this._tree,e);return n[c]=t(n[c]),this}values(){return new i(this,o)}[Symbol.iterator](){return this.entries()}}m.from=function(e){const t=new m;for(let[n,i]of e)t.set(n,i);return t},m.fromObject=function(e){return m.from(Object.entries(e))};const _=function(e,t,n=[]){if(0===t.length)return[e,n];const i=Object.keys(e).find(e=>e!==c&&t.startsWith(e));return void 0===i?_(void 0,"",[...n,[e,t]]):_(e[i],t.slice(i.length),[...n,[e,i]])},y=function(e,t){if(0===t.length)return e;const n=Object.keys(e).find(e=>e!==c&&t.startsWith(e));return void 0!==n?y(e[n],t.slice(n.length)):void 0},b=function(e,t){if(0===t.length)return e;const n=Object.keys(e).find(e=>e!==c&&t.startsWith(e));if(void 0===n){const n=Object.keys(e).find(e=>e!==c&&e.startsWith(t[0]));if(void 0!==n){const i=g(t,n);return e[i]={[n.slice(i.length)]:e[n]},delete e[n],b(e[i],t.slice(i.length))}return e[t]={},e[t]}return b(e[n],t.slice(n.length))},g=function(e,t,n=0,i=Math.min(e.length,t.length),s=""){return n>=i?s:e[n]!==t[n]?s:g(e,t,n+1,i,s+e[n])},x=function(e,t){const[n,i]=_(e,t);if(void 0===n)return;delete n[c];const s=Object.keys(n);0===s.length&&v(i),1===s.length&&O(i,s[0],n[s[0]])},v=function(e){if(0===e.length)return;const[t,n]=k(e);delete t[n],0===Object.keys(t).length&&v(e.slice(0,-1))},O=function(e,t,n){if(0===e.length)return;const[i,s]=k(e);i[s+t]=n,delete i[s]},k=function(e){return e[e.length-1]};var z=m;const j="or";class w{constructor(e={}){this._options={...D,...e},this._options.searchOptions={...$,...this._options.searchOptions||{}};const{fields:t}=this._options;if(null==t)throw new Error('Option "fields" must be provided');this._index=new z,this._documentCount=0,this._documentIds={},this._fieldIds={},M(this,t)}add(e){const{tokenize:t,processTerm:n,fields:i,idField:s}=this._options;if(null==e[s])throw new Error(`Document does not have ID field "${s}"`);const r=C(this,e[s]);i.filter(t=>null!=e[t]).forEach(i=>{t(e[i]).forEach(e=>{E(this,this._fieldIds[i],r,n(e))})})}addAll(e){e.forEach(e=>this.add(e))}remove(e){const{tokenize:t,processTerm:n,fields:i,idField:s}=this._options;if(null==e[s])throw new Error(`Document does not have ID field "${s}"`);const[r]=Object.entries(this._documentIds).find(([t,n])=>e[s]===n)||[];if(null==r)throw new Error(`Cannot remove document with ID ${e[s]}: it is not in the index`);i.filter(t=>null!=e[t]).forEach(i=>{t(e[i]).forEach(e=>{I(this,this._fieldIds[i],r,n(e))})}),this._documentCount-=1}search(e,t={}){const{tokenize:n,processTerm:i,searchOptions:s}=this._options;t={...s,...t};const r=n(e).map(i).map(T(t)).map(e=>this.executeQuery(e,t)),o=this.combineResults(r,t.combineWith);return Object.entries(o).map(([e,{score:t,match:n}])=>({id:this._documentIds[e],score:t,match:n})).sort(({score:e},{score:t})=>e<t?1:-1)}get documentCount(){return this._documentCount}executeQuery(e,t={}){const n=((t={...this._options.defaultSearchOptions,...t}).fields||this._options.fields).reduce((e,t)=>({...e,[t]:e[t]||1}),t.boost||{});if(!e.fuzzy&&!e.prefix)return W(this,e.term,n,this._index.get(e.term));const i=[];if(e.fuzzy){const t=e.fuzzy<1?Math.round(e.term.length*e.fuzzy):e.fuzzy;Object.entries(this._index.fuzzyGet(e.term,t)).forEach(([e,[t,s]])=>{i.push(W(this,e,n,t,s))})}return e.prefix&&this._index.atPrefix(e.term).forEach((t,s)=>{i.push(W(this,t,n,s,t.length-e.term.length))}),i.reduce(P[j],{})}combineResults(e,t=j){if(0===e.length)return{};const n=t.toLowerCase();return e.reduce(P[n],null)}toJSON(){return{index:this._index,documentCount:this._documentCount,documentIds:this._documentIds,fieldIds:this._fieldIds}}toJS(){this.toJSON()}}w.loadJSON=function(e,t={}){return w.loadJS(JSON.parse(e),t)},w.loadJS=function(e,t={}){const{index:{_tree:n,_prefix:i},documentCount:s,documentIds:r,fieldIds:o}=e,c=new w(t);return c._index=new z(n,i),c._documentCount=s,c._documentIds=r,c._fieldIds=o,c},w.SearchableMap=z;const E=function(e,t,n,i){e._index.update(i,e=>{const i=(e=e||{})[t]||{df:0,ds:{}};return null==i.ds[n]&&(i.df+=1),i.ds[n]=(i.ds[n]||0)+1,{...e,[t]:i}})},I=function(e,t,n,i){e._index.has(i)?(e._index.update(i,s=>{const r=s[t];return null==r||null==r.ds[n]?(S(e,n,t,i),s):r.df<=1?(delete s[t],s):(r.df-=1,r.ds[n]<=1?(delete r.ds[n],s):(r.ds[n]-=1,{...s,[t]:r}))}),0===Object.keys(e._index.get(i)).length&&e._index.delete(i)):S(e,n,t,i)},S=function(e,t,n,i){if(null==console||null==console.warn)return;const s=Object.entries(e._fieldIds).find(([e,t])=>t===n)[0];console.warn(`MiniSearch: document with ID ${e._documentIds[t]} has changed before removal: term "${i}" was not present in field "${s}". Removing a document after it has changed can corrupt the index!`)},C=function(e,t){const n=e._documentCount;return e._documentIds[n]=t,e._documentCount+=1,n},M=function(e,t){t.forEach((t,n)=>{e._fieldIds[t]=n})},W=function(e,t,n,i,s=0){return null==i?{}:Object.entries(n).reduce((n,[r,o])=>{const{df:c,ds:u}=i[e._fieldIds[r]]||{ds:{}};return Object.entries(u).forEach(([i,u])=>{const d=o/(1+.333*o*s);n[i]=n[i]||{score:0,match:{}},n[i].match[t]=n[i].match[t]||[],n[i].score+=d*J(u,c,e._documentCount),n[i].match[t].push(r)}),n},{})},P={[j]:function(e,t){return Object.entries(t).reduce((e,[t,{score:n,match:i}])=>(null==e[t]?e[t]={score:n,match:i}:(e[t].score+=n,Object.assign(e[t].match,i)),e),e||{})},and:function(e,t){return null==e?t:Object.entries(t).reduce((t,[n,{score:i,match:s}])=>void 0===e[n]?t:(t[n]=t[n]||{},t[n].score=Math.min(e[n].score,i),t[n].match={...e[n].match,...s},t),{})}},J=function(e,t,n){return e*Math.log(n/t)},T=e=>t=>{return{term:t,fuzzy:"function"==typeof e.fuzzy?e.fuzzy(t):e.fuzzy,prefix:"function"==typeof e.prefix?e.prefix(t):e.prefix}},D={idField:"id",tokenize:e=>e.split(/\W+/).filter(e=>e.length>1),processTerm:e=>e.toLowerCase()},$={combineWith:j};var N=w;t.default=N}]).default});
{
"name": "minisearch",
"version": "0.1.6",
"version": "0.1.7",
"description": "fun with fulltext search",

@@ -5,0 +5,0 @@ "main": "dist/minisearch.js",

@@ -7,3 +7,3 @@ # MiniSearch

## Use case:
## Use case

@@ -21,18 +21,21 @@ `MiniSearch` addresses use cases where full-text search features are needed

## Design goals:
* Memory-efficient index, able to store tens of thousands of documents and
terms in memory, even in the browser.
## Features
* Memory-efficient index, smaller than most other libraries, designed to
support memory-constrained use cases like mobile browsers.
* Exact match, prefix match and fuzzy match, all with a single performant and
multi-purpose index data structure.
* Small and maintainable code base, well tested, with no external dependency.
* Mutable index, capable of adding and removing documents at any time
* Provide good building blocks that empower developers to build solutions to
their specific problems, rather than try to offer a general-purpose tool to
satisfy every use-case at the cost of complexity.
* Simple API, providing building blocks to build solutions to
their specific problems
## Installation:
* Zero external dependencies, small code-base, well tested
## Installation
With `npm`:

@@ -50,9 +53,13 @@

## Usage:
## Usage
[API documentation](https://lucaong.github.io/minisearch/identifiers.html) is
available, but here are some quick examples:
Refer to the [API
documentation](https://lucaong.github.io/minisearch/identifiers.html) for
details, but here are some quick examples. All the examples use the `ES6`
syntax.
### Basic usage
```javascript
// A collection of documents for our example
// A collection of documents for our examples
const documents = [

@@ -74,21 +81,23 @@ { id: 1, title: 'Moby Dick', text: 'Call me Ishmael. Some years ago...' },

// => [ { id: 2, score: 2.77258, match: { ... } }, { id: 4, score: 1.38629, match: { ... } } ]
```
### Search options
`MiniSearch` supports several options for more advanced search behavior:
```javascript
// Search only specific fields
results = miniSearch.search('zen', { fields: ['title'] })
miniSearch.search('zen', { fields: ['title'] })
// Boost fields
results = miniSearch.search('zen', { boost: { title: 2 } })
// Boost some fields (here "title")
miniSearch.search('zen', { boost: { title: 2 } })
// Prefix search
results = miniSearch.search('moto', {
termToQuery: term => ({ term, prefix: true })
})
// Prefix search (so that 'moto' will match 'motorcycle')
miniSearch.search('moto', { prefix: true })
// Fuzzy search (in this example, with a max edit distance of 0.2 * term length,
// rounded to nearest integer)
results = miniSearch.search('ismael', {
termToQuery: term => ({ term, fuzzy: 0.2 })
})
// Fuzzy search, in this example, with a max edit distance of 0.2 * term length,
// rounded to nearest integer. The mispelled 'ismael' will match 'ishmael'.
miniSearch.search('ismael', { fuzzy: 0.2 })
// Set default search options upon initialization
// You can set the default search options upon initialization
miniSearch = new MiniSearch({

@@ -98,3 +107,3 @@ fields: ['title', 'text'],

boost: { title: 2 },
termToQuery: term => ({ term, fuzzy: 0.2 })
fuzzy: 0.2
}

@@ -104,4 +113,8 @@ })

// Will now by default perform fuzzy search and boost "title":
results = miniSearch.search('zen and motorcycles')
// It will now by default perform fuzzy search and boost "title":
miniSearch.search('zen and motorcycles')
```
The [API documentation](https://lucaong.github.io/minisearch/identifiers.html)
has more details about other configuration options (tokenization, term
processing, etc.)

@@ -7,3 +7,4 @@ import Benchmark from 'benchmark'

ms.search('virtute e conoscienza', {
termToQuery: term => ({ term, fuzzy: 0.2, prefix: true })
fuzzy: 0.2,
prefix: true
})

@@ -10,0 +11,0 @@ })

@@ -166,3 +166,4 @@ import SearchableMap from './SearchableMap/SearchableMap.js'

* @param {Object<string, number>} [options.boost] - Key-value object of boosting values for fields
* @param {function(term: string): {term: !string, prefix: ?boolean, fuzzy: ?number}} [options.termToQuery] - Function specifying how a term is turned into a query (whether to perform fuzzy search, prefix search, etc.)
* @param {boolean|function} [options.prefix] - Whether to perform prefix search. Value can be a boolean, or a function computing the boolean from the term.
* @param {number|function} [options.fuzzy] - If set to a number greater than or equal 1, it performs fuzzy search within a maximum edit distance equal to that value. If set to a number less than 1, it performs fuzzy search with a maximum edit distance equal to the term length times the value, rouded at the nearest integer. If set to a function, it calls the function passing each search term and expects a numeric value indicating the maximum edit distance, or a falsy falue if fuzzy search should not be performed.
* @param {string} [options.combineWith='OR'] - How to combine term queries (it can be 'OR' or 'AND')

@@ -188,5 +189,3 @@ * @return {Array<{ id: any, score: number, match: Object }>} A sorted array of scored document IDs matching the search

* // containing terms that start with "moto" or "neuro")
* miniSearch.search('moto neuro', {
* termToQuery: term => ({ term, prefix: true })
* })
* miniSearch.search('moto neuro', { prefix: true })
*

@@ -197,5 +196,3 @@ * @example

* // (rounded to nearest integer)
* miniSearch.search('ismael', {
* termToQuery: term => ({ term, fuzzy: 0.2 })
* })
* miniSearch.search('ismael', { fuzzy: 0.2 })
*

@@ -205,6 +202,15 @@ * @example

* miniSearch.search('ismael mob', {
* termToQuery: term => ({ term, prefix: true, fuzzy: 0.2 })
* prefix: true,
* fuzzy: 0.2
* })
*
* @example
* // Perform fuzzy and prefix search depending on the search term. Here
* // performing prefix and fuzzy search only on terms longer than 3 characters
* miniSearch.search('ismael mob', {
* prefix: term => term.length > 3
* fuzzy: term => term.length > 3 ? 0.2 : null
* })
*
* @example
* // Combine search terms with AND (to match only documents that contain both

@@ -217,3 +223,3 @@ * // "motorcycle" and "art")

options = { ...searchOptions, ...options }
const queries = tokenize(queryString).map(processTerm).map(options.termToQuery)
const queries = tokenize(queryString).map(processTerm).map(termToQuery(options))
const results = queries.map(query => this.executeQuery(query, options))

@@ -422,2 +428,12 @@ const combinedResults = this.combineResults(results, options.combineWith)

const termToQuery = (options) => (term) => {
const fuzzy = (typeof options.fuzzy === 'function')
? options.fuzzy(term)
: options.fuzzy
const prefix = (typeof options.prefix === 'function')
? options.prefix(term)
: options.prefix
return { term, fuzzy, prefix }
}
const defaultOptions = {

@@ -430,3 +446,2 @@ idField: 'id',

const defaultSearchOptions = {
termToQuery: term => ({ term }),
combineWith: OR

@@ -433,0 +448,0 @@ }

@@ -148,3 +148,3 @@ /* eslint-env jest */

it('executes fuzzy search', () => {
const results = ms.search('camin memory', { termToQuery: term => ({ term, fuzzy: 2 }) })
const results = ms.search('camin memory', { fuzzy: 2 })
expect(results.length).toEqual(2)

@@ -155,3 +155,3 @@ expect(results.map(({ id }) => id)).toEqual([1, 3])

it('executes prefix search', () => {
const results = ms.search('que', { termToQuery: term => ({ term, prefix: true }) })
const results = ms.search('que', { prefix: true })
expect(results.length).toEqual(2)

@@ -162,3 +162,3 @@ expect(results.map(({ id }) => id)).toEqual([2, 3])

it('combines prefix search and fuzzy search', () => {
const results = ms.search('cammino quel', { termToQuery: term => ({ term, fuzzy: 0.25, prefix: true }) })
const results = ms.search('cammino quel', { fuzzy: 0.25, prefix: true })
expect(results.length).toEqual(3)

@@ -168,2 +168,11 @@ expect(results.map(({ id }) => id)).toEqual([2, 1, 3])

it('accepts a function to compute fuzzy and prefix options from term', () => {
const results = ms.search('quel comedia', {
fuzzy: term => term.length > 4 ? 2 : false,
prefix: term => term.length > 4
})
expect(results.length).toEqual(2)
expect(results.map(({ id }) => id)).toEqual([2, 1])
})
describe('match data', () => {

@@ -195,3 +204,3 @@ const documents = [

it('reports correct info for fuzzy and prefix queries', () => {
const results = ms.search('vi nuova', { termToQuery: term => ({ term, fuzzy: 0.2, prefix: true }) })
const results = ms.search('vi nuova', { fuzzy: 0.2, prefix: true })
expect(results.map(({ match }) => match)).toEqual([

@@ -198,0 +207,0 @@ { vita: ['title', 'text'], nova: ['title'] },

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc