From fa4a3bc0367bfb2ec2383bea02290b65d3a0fb07 Mon Sep 17 00:00:00 2001 From: DominikDoom Date: Sun, 21 Apr 2024 17:58:14 +0200 Subject: [PATCH] =?UTF-8?q?Use=20=CE=BCFuzzy=20instead=20as=20it=20is=20fa?= =?UTF-8?q?ster=20and=20more=20configurable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- javascript/_fuzzysort.min.js | 2 - javascript/_result.js | 1 + javascript/_uFuzzy.js | 134 ++++++++++++++++++++++++++++++++++ javascript/tagAutocomplete.js | 28 +++---- 4 files changed, 150 insertions(+), 15 deletions(-) delete mode 100644 javascript/_fuzzysort.min.js create mode 100644 javascript/_uFuzzy.js diff --git a/javascript/_fuzzysort.min.js b/javascript/_fuzzysort.min.js deleted file mode 100644 index ed074ba..0000000 --- a/javascript/_fuzzysort.min.js +++ /dev/null @@ -1,2 +0,0 @@ -// https://github.com/farzher/fuzzysort v2.0.4 -((r,e)=>{"function"==typeof define&&define.amd?define([],e):"object"==typeof module&&module.exports?module.exports=e():r.fuzzysort=e()})(this,r=>{"use strict";var i,o,e,a,f=r=>{var e=v(r="string"!=typeof r?"":r);return{target:r,t:e.i,o:e.v,u:N,l:e.g,score:N,_:[0],obj:N}},t=r=>{r=(r="string"!=typeof r?"":r).trim();var e=v(r),a=[];if(e.p)for(var f,t=r.split(/\s+/),t=[...new Set(t)],n=0;n{var e;return 999{var e;return 999{if(!1===a&&r.p)return j(r,e);for(var a=r.i,f=r.v,t=f[0],n=e.o,i=f.length,o=n.length,v=0,s=0,u=0;;){if(t===n[s]){if(C[u++]=s,++v===i)break;t=f[v]}if(o<=++s)return N}var v=0,l=!1,g=0,d=e.u,c=(d===N&&(d=e.u=k(e.target)),s=0===C[0]?0:d[C[0]-1],0);if(s!==o)for(;;)if(o<=s){if(v<=0)break;if(200<++c)break;--v;s=d[L[--g]]}else if(f[v]===n[s]){if(L[g++]=s,++v===i){l=!0;break}++s}else s=d[s];var w=e.t.indexOf(a,C[0]),r=~w;if(r&&!l)for(var _=0;_{for(var a=new Set,f=0,t=N,n=0,i=r.h,o=0;of)return r;t.score=f;var u,o=0;for(u of a)t._[o++]=u;return t._.j=o,t},v=r=>{for(var e=r.length,a=r.toLowerCase(),f=[],t=0,n=!1,i=0;i{for(var e=r.length,a=(r=>{for(var e=r.length,a=[],f=0,t=!1,n=!1,i=0;i{for(var e=J,a=r.length,f=0;f{var a=r[e];if(void 0!==a)return a;for(var f=e,t=(f=Array.isArray(e)?f:e.split(".")).length,n=-1;r&&++n"object"==typeof r,H=1/0,J=-H,K=[],N=null,O=(i=[],o=K.total=0,a=r=>{for(var e=i[t=0],a=1;a>1]=i[t],a=1+(t<<1)}for(var n=t-1>>1;0>1)i[t]=i[n];i[t]=e},(e={}).add=r=>{var e=o;i[o++]=r;for(var a=e-1>>1;0>1)i[e]=i[a];i[e]=r},e.k=r=>{var e;if(0!==o)return e=i[0],i[0]=i[--o],a(),e},e.C=r=>{if(0!==o)return i[0]},e.L=r=>{i[0]=r,a()},e);return{single:(r,e)=>{var a;return"farzher"==r?{target:"farzher was here (^-^*)/",score:0,_:[0]}:!r||!e||(r=q(r),G(e)||(e=M(e)),((a=r.g)&e.l)!==a)?N:D(r,e)},go:(r,e,a)=>{if("farzher"==r)return[{target:"farzher was here (^-^*)/",score:0,_:[0],obj:e?e[0]:N}];if(!r)if(a&&a.all){var f=e;var t=a;var n=[],i=(n.total=f.length,t&&t.limit||H);if(t&&t.key)for(var o=0;o=i)return n}else if(t&&t.keys)for(o=0;o=0;--g){s=F(v,t.keys[g]);if(!s){l[g]=N;continue}if(!G(s))s=M(s);s.score=J;s._.j=0;l[g]=s}l.obj=v;l.score=J;n.push(l);if(n.length>=i)return n}else for(o=0;o=i)return n}return n;return}else return K;var d=q(r),c=d.g,w=(d.p,a&&a.threshold||J),_=a&&a.limit||H,b=0,p=0,x=e.length;if(a&&a.key)for(var h=a.key,y=0;yO.C().score&&O.L(B)))}else if(a&&a.keys)for(var k=a.scoreFn||E,C=a.keys,L=C.length,y=0;yO.C().score&&O.L(S)))}else for(var m,B,y=0;yO.C().score&&O.L(B)));if(0===b)return K;for(var I=new Array(b),y=b-1;0<=y;--y)I[y]=O.k();return I.total=b+p,I},highlight:(r,e,a)=>{if("function"==typeof e){var f=e;if((l=r)===N)return N;for(var t=l.target,n=t.length,i=(i=l._).slice(0,i.j).sort((r,e)=>r-e),o="",v=0,s=0,u=!1,l=[],g=0;g"),void 0===a&&(a="");for(var c="",w=0,_=!1,b=r.target,p=b.length,x=(x=r._).slice(0,x.j).sort((r,e)=>r-e),h=0;hr._.slice(0,r._.j).sort((r,e)=>r-e),cleanup:()=>{n.clear(),s.clear(),C=[],L=[]}}}); \ No newline at end of file diff --git a/javascript/_result.js b/javascript/_result.js index 8b81a1b..c90b4e6 100644 --- a/javascript/_result.js +++ b/javascript/_result.js @@ -30,6 +30,7 @@ class AutocompleteResult { meta = null; hash = null; sortKey = null; + highlightedText = null; // Constructor constructor(text, type) { diff --git a/javascript/_uFuzzy.js b/javascript/_uFuzzy.js new file mode 100644 index 0000000..ed45e73 --- /dev/null +++ b/javascript/_uFuzzy.js @@ -0,0 +1,134 @@ +class TacFuzzy { + /*! https://github.com/leeoniya/uFuzzy (v1.0.14) */ + static #uFuzzy = function(){"use strict";const e=new Intl.Collator("en",{numeric:!0,sensitivity:"base"}).compare,t=1/0,l=e=>e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n="eexxaacctt",r=/\p{P}/gu,i=(e,t,l)=>e.replace("A-Z",t).replace("a-z",l),s={unicode:!1,alpha:null,interSplit:"[^A-Za-z\\d']+",intraSplit:"[a-z][A-Z]",interBound:"[^A-Za-z\\d]",intraBound:"[A-Za-z]\\d|\\d[A-Za-z]|[a-z][A-Z]",interLft:0,interRgt:0,interChars:".",interIns:t,intraChars:"[a-z\\d']",intraIns:null,intraContr:"'[a-z]{1,2}\\b",intraMode:0,intraSlice:[1,t],intraSub:null,intraTrn:null,intraDel:null,intraFilt:()=>!0,sort:(t,l)=>{let{idx:n,chars:r,terms:i,interLft2:s,interLft1:a,start:g,intraIns:u,interIns:f}=t;return n.map(((e,t)=>t)).sort(((t,h)=>r[h]-r[t]||u[t]-u[h]||i[h]+s[h]+.5*a[h]-(i[t]+s[t]+.5*a[t])||f[t]-f[h]||g[t]-g[h]||e(l[n[t]],l[n[h]])))}},a=(e,l)=>0==l?"":1==l?e+"??":l==t?e+"*?":e+`{0,${l}}?`,g="(?:\\b|_)";function u(e){e=Object.assign({},s,e);let{unicode:t,interLft:u,interRgt:f,intraMode:c,intraSlice:o,intraIns:p,intraSub:d,intraTrn:m,intraDel:x,intraContr:b,intraSplit:R,interSplit:L,intraBound:A,interBound:S,intraChars:z}=e;p??=c,d??=c,m??=c,x??=c;let E=e.letters??e.alpha;if(null!=E){let e=E.toLocaleUpperCase(),t=E.toLocaleLowerCase();L=i(L,e,t),R=i(R,e,t),S=i(S,e,t),A=i(A,e,t),z=i(z,e,t),b=i(b,e,t)}let I=t?"u":"";const C='".+?"',y=RegExp(C,"gi"+I),k=RegExp(`(?:\\s+|^)-(?:${z}+|${C})`,"gi"+I);let{intraRules:j}=e;null==j&&(j=e=>{let t=s.intraSlice,l=0,n=0,r=0,i=0;if(/[^\d]/.test(e)){let s=e.length;s>4?(t=o,l=p,n=d,r=m,i=x):3>s||(r=Math.min(m,1),4==s&&(l=Math.min(p,1)))}return{intraSlice:t,intraIns:l,intraSub:n,intraTrn:r,intraDel:i}});let Z=!!R,$=RegExp(R,"g"+I),w=RegExp(L,"g"+I),M=RegExp("^"+L+"|"+L+"$","g"+I),B=RegExp(b,"gi"+I);const D=e=>{let t=[];e=(e=e.replace(y,(e=>(t.push(e),n)))).replace(M,"").toLocaleLowerCase(),Z&&(e=e.replace($,(e=>e[0]+" "+e[1])));let l=0;return e.split(w).filter((e=>""!=e)).map((e=>e===n?t[l++]:e))},T=/[^\d]+|\d+/g,F=(t,n=0,r=!1)=>{let i=D(t);if(0==i.length)return[];let s,h=Array(i.length).fill("");if(i=i.map(((e,t)=>e.replace(B,(e=>(h[t]=e,""))))),1==c)s=i.map(((e,t)=>{if('"'===e[0])return l(e.slice(1,-1));let n="";for(let l of e.matchAll(T)){let e=l[0],{intraSlice:r,intraIns:i,intraSub:s,intraTrn:g,intraDel:u}=j(e);if(i+s+g+u==0)n+=e+h[t];else{let[l,f]=r,c=e.slice(0,l),o=e.slice(f),p=e.slice(l,f);1==i&&1==c.length&&c!=p[0]&&(c+="(?!"+c+")");let d=p.length,m=[e];if(s)for(let e=0;d>e;e++)m.push(c+p.slice(0,e)+z+p.slice(e+1)+o);if(g)for(let e=0;d-1>e;e++)p[e]!=p[e+1]&&m.push(c+p.slice(0,e)+p[e+1]+p[e]+p.slice(e+2)+o);if(u)for(let e=0;d>e;e++)m.push(c+p.slice(0,e+1)+"?"+p.slice(e+1)+o);if(i){let e=a(z,1);for(let t=0;d>t;t++)m.push(c+p.slice(0,t)+e+p.slice(t)+o)}n+="(?:"+m.join("|")+")"+h[t]}}return n}));else{let e=a(z,p);2==n&&p>0&&(e=")("+e+")("),s=i.map(((t,n)=>'"'===t[0]?l(t.slice(1,-1)):t.split("").map(((e,t,l)=>(1==p&&0==t&&l.length>1&&e!=l[t+1]&&(e+="(?!"+e+")"),e))).join(e)+h[n]))}let o=2==u?g:"",d=2==f?g:"",m=d+a(e.interChars,e.interIns)+o;return n>0?r?s=o+"("+s.join(")"+d+"|"+o+"(")+")"+d:(s="("+s.join(")("+m+")(")+")",s="(.??"+o+")"+s+"("+d+".*)"):(s=s.join(m),s=o+s+d),[RegExp(s,"i"+I),i,h]},O=(e,t,l)=>{let[n]=F(t);if(null==n)return null;let r=[];if(null!=l)for(let t=0;l.length>t;t++){let i=l[t];n.test(e[i])&&r.push(i)}else for(let t=0;e.length>t;t++)n.test(e[t])&&r.push(t);return r};let v=!!A,U=RegExp(S,I),N=RegExp(A,I);const P=(t,l,n)=>{let[r,i,s]=F(n,1),[a]=F(n,2),g=i.length,h=t.length,c=Array(h).fill(0),o={idx:Array(h),start:c.slice(),chars:c.slice(),terms:c.slice(),interIns:c.slice(),intraIns:c.slice(),interLft2:c.slice(),interRgt2:c.slice(),interLft1:c.slice(),interRgt1:c.slice(),ranges:Array(h)},p=1==u||1==f,d=0;for(let n=0;t.length>n;n++){let h=l[t[n]],c=h.match(r),m=c.index+c[1].length,x=m,b=!1,R=0,L=0,A=0,S=0,z=0,E=0,C=0,y=0,k=[];for(let t=0,l=2;g>t;t++,l+=2){let n=c[l].toLocaleLowerCase(),r=i[t],a='"'==r[0]?r.slice(1,-1):r+s[t],o=a.length,d=n.length,j=n==a;if(!j&&c[l+1].length>=o){let e=c[l+1].toLocaleLowerCase().indexOf(a);e>-1&&(k.push(x,d,e,o),x+=_(c,l,e,o),n=a,d=o,j=!0,0==t&&(m=x))}if(p||j){let e=x-1,r=x+d,i=!1,s=!1;if(-1==e||U.test(h[e]))j&&R++,i=!0;else{if(2==u){b=!0;break}if(v&&N.test(h[e]+h[e+1]))j&&L++,i=!0;else if(1==u){let e=c[l+1],r=x+d;if(e.length>=o){let s,g=0,u=!1,f=RegExp(a,"ig"+I);for(;s=f.exec(e);){g=s.index;let e=r+g,t=e-1;if(-1==t||U.test(h[t])){R++,u=!0;break}if(N.test(h[t]+h[e])){L++,u=!0;break}}u&&(i=!0,k.push(x,d,g,o),x+=_(c,l,g,o),n=a,d=o,j=!0,0==t&&(m=x))}if(!i){b=!0;break}}}if(r==h.length||U.test(h[r]))j&&A++,s=!0;else{if(2==f){b=!0;break}if(v&&N.test(h[r-1]+h[r]))j&&S++,s=!0;else if(1==f){b=!0;break}}j&&(z+=o,i&&s&&E++)}if(d>o&&(y+=d-o),t>0&&(C+=c[l-1].length),!e.intraFilt(a,n,x)){b=!0;break}g-1>t&&(x+=d+c[l+1].length)}if(!b){o.idx[d]=t[n],o.interLft2[d]=R,o.interLft1[d]=L,o.interRgt2[d]=A,o.interRgt1[d]=S,o.chars[d]=z,o.terms[d]=E,o.interIns[d]=C,o.intraIns[d]=y,o.start[d]=m;let e=h.match(a),l=e.index+e[1].length,r=k.length,i=r>0?0:1/0,s=r-4;for(let t=2;e.length>t;)if(i>s||k[i]!=l)l+=e[t].length,t++;else{let n=k[i+1],r=k[i+2],s=k[i+3],a=t,g="";for(let t=0;n>t;a++)g+=e[a],t+=e[a].length;e.splice(t,a-t,g),l+=_(e,t,r,s),i+=4}l=e.index+e[1].length;let g=o.ranges[d]=[],u=l,f=l;for(let t=2;e.length>t;t++){let n=e[t].length;l+=n,t%2==0?f=l:n>0&&(g.push(u,f),u=f=l)}f>u&&g.push(u,f),d++}}if(t.length>d)for(let e in o)o[e]=o[e].slice(0,d);return o},_=(e,t,l,n)=>{let r=e[t]+e[t+1].slice(0,l);return e[t-1]+=r,e[t]=e[t+1].slice(l,l+n),e[t+1]=e[t+1].slice(l+n),r.length};return{search:(...t)=>((t,n,i,s=1e3,a)=>{i=i?!0===i?5:i:0;let g=null,u=null,f=[];n=n.replace(k,(e=>{let t=e.trim().slice(1);return t='"'===t[0]?l(t.slice(1,-1)):t.replace(r,""),""!=t&&f.push(t),""}));let c,o=D(n);if(f.length>0){if(c=RegExp(f.join("|"),"i"+I),0==o.length){let e=[];for(let l=0;t.length>l;l++)c.test(t[l])||e.push(l);return[e,null,null]}}else if(0==o.length)return[null,null,null];if(i>0){let e=D(n);if(e.length>1){let l=e.slice().sort(((e,t)=>t.length-e.length));for(let e=0;l.length>e;e++){if(0==a?.length)return[[],null,null];a=O(t,l[e],a)}if(e.length>i)return[a,null,null];g=h(e).map((e=>e.join(" "))),u=[];let n=new Set;for(let e=0;g.length>e;e++)if(a.length>n.size){let l=a.filter((e=>!n.has(e))),r=O(t,g[e],l);for(let e=0;r.length>e;e++)n.add(r[e]);u.push(r)}else u.push([])}}null==g&&(g=[n],u=[a?.length>0?a:O(t,n)]);let p=null,d=null;if(f.length>0&&(u=u.map((e=>e.filter((e=>!c.test(t[e])))))),s>=u.reduce(((e,t)=>e+t.length),0)){p={},d=[];for(let l=0;u.length>l;l++){let n=u[l];if(null==n||0==n.length)continue;let r=g[l],i=P(n,t,r),s=e.sort(i,t,r);if(l>0)for(let e=0;s.length>e;e++)s[e]+=d.length;for(let e in i)p[e]=(p[e]??[]).concat(i[e]);d=d.concat(s)}}return[[].concat(...u),p,d]})(...t),split:D,filter:O,info:P,sort:e.sort}}const f=(()=>{let e={A:"ÁÀÃÂÄĄ",a:"áàãâäą",E:"ÉÈÊËĖ",e:"éèêëę",I:"ÍÌÎÏĮ",i:"íìîïį",O:"ÓÒÔÕÖ",o:"óòôõö",U:"ÚÙÛÜŪŲ",u:"úùûüūų",C:"ÇČĆ",c:"çčć",L:"Ł",l:"ł",N:"ÑŃ",n:"ñń",S:"ŠŚ",s:"šś",Z:"ŻŹ",z:"żź"},t=new Map,l="";for(let n in e)e[n].split("").forEach((e=>{l+=e,t.set(e,n)}));let n=RegExp(`[${l}]`,"g"),r=e=>t.get(e);return e=>{if("string"==typeof e)return e.replace(n,r);let t=Array(e.length);for(let l=0;e.length>l;l++)t[l]=e[l].replace(n,r);return t}})();function h(e){let t,l,n=(e=e.slice()).length,r=[e.slice()],i=Array(n).fill(0),s=1;for(;n>s;)s>i[s]?(t=s%2&&i[s],l=e[s],e[s]=e[t],e[t]=l,++i[s],s=1,r.push(e.slice())):(i[s]=0,++s);return r}const c=(e,t)=>t?`${e}`:e,o=(e,t)=>e+t;return u.latinize=f,u.permute=e=>h([...Array(e.length).keys()]).sort(((e,t)=>{for(let l=0;e.length>l;l++)if(e[l]!=t[l])return e[l]-t[l];return 0})).map((t=>t.map((t=>e[t])))),u.highlight=function(e,t,l=c,n="",r=o){n=r(n,l(e.substring(0,t[0]),!1))??n;for(let i=0;t.length>i;i+=2)n=r(n,l(e.substring(t[i],t[i+1]),!0))??n,t.length-3>i&&(n=r(n,l(e.substring(t[i+1],t[i+2]),!1))??n);return r(n,l(e.substring(t[t.length-1]),!1))??n},u}(); + + // Set up uFuzzy for TAC + + // Type-ahead sorting (from uFuzzy demo) + static #cmp = new Intl.Collator('en').compare; + static #typeAheadSort = (info, haystack, needle) => { + let { + idx, + chars, + terms, + interLft2, + interLft1, + // interRgt2, + // interRgt1, + start, + intraIns, + interIns, + } = info; + + return idx.map((v, i) => i).sort((ia, ib) => ( + // most contig chars matched + chars[ib] - chars[ia] || + // least char intra-fuzz (most contiguous) + intraIns[ia] - intraIns[ib] || + // earliest start of match + start[ia] - start[ib] || + // shortest match first + haystack[idx[ia]].length - haystack[idx[ib]].length || + // most prefix bounds, boosted by full term matches + ( + (terms[ib] + interLft2[ib] + 0.5 * interLft1[ib]) - + (terms[ia] + interLft2[ia] + 0.5 * interLft1[ia]) + ) || + // highest density of match (least span) + // span[ia] - span[ib] || + // highest density of match (least term inter-fuzz) + interIns[ia] - interIns[ib] || + // alphabetic + this.#cmp(haystack[idx[ia]], haystack[idx[ib]]) + )) + }; + // Options + static #oooPermute = true; + static #infoThresh = Infinity; // Make sure we are always getting info, performance isn't that bad for the default tag sets + static #usePrefixCache = false; + static #tacFuzzyOpts = { + intraIns: Infinity, + interIns: Infinity, + intraChars: "[\\w\\-']", // Alphanumeric, hyphen, underscore & apostrophe + interLft: 1, // loose + sort: this.#typeAheadSort + } + static #u = new this.#uFuzzy(this.#tacFuzzyOpts); + // Prefilter function to reduce search scope (from uFuzzy demo) + static #prefixCache = []; + static #prefilter = (haystack, needle) => { + // find longest matching prefix <= needle.length + let li = null; + this.#prefixCache.forEach((c, i) => { + if (c.needle.length <= needle.length && needle.indexOf(c.needle) == 0) { + if (li == null || c.needle.length > this.#prefixCache[li].needle.length) { + li = i; + } + } + }); + + // when not outOfOrder, reset prefix cache if what's in cache has no prefix of current needle + if (this.#prefixCache.length > 0 && li == null) + this.#prefixCache.length = 0; + + let idxs = ( + li == null ? this.#u.filter(haystack, needle) : + this.#prefixCache[li].needle.length == needle.length ? this.#prefixCache[li].idxs : + this.#u.filter(haystack, needle, this.#prefixCache[li].idxs) + ); + + if (idxs.length <= 1e4 && (li == null || needle != this.#prefixCache[li].needle)) { + this.#prefixCache.push({ + needle, + idxs, + }); + + let cacheLen = this.#prefixCache.length; + + // trim cache to 10 prefixes + if (cacheLen > 10) + this.#prefixCache = this.#prefixCache.slice(1); + } + + return idxs; + } + + /** + * uFuzzy search function adjusted for TACs requirements + * @param {String[]} haystack - The list of strings to search + * @param {String} needle - The search term (tagword) + * @returns A list of uFuzzy search results + */ + static search = (haystack, needle) => { + let preFiltered = this.#usePrefixCache ? this.#prefilter(haystack, needle) : null; + + let [idxs, info, order] = this.#u.search(haystack, needle, this.#oooPermute, this.#infoThresh, preFiltered); + + if (idxs != null) { + if (info != null) { + this.toStr = oi => { + let hi = info.idx[oi]; + return this.#uFuzzy.highlight(haystack[hi], info.ranges[oi]); + }; + return { + haystackIndices: order.map(oi => info.idx[oi]), + orderIndices: order + } + } + else if (idxs.length > 0) { + this.toStr = idx => haystack[idx]; + return idxs; + } + } + + return []; + } + /** Gets the string representation function for the uFuzzy results. + * Is overwritten by the search function to apply higlighting on matches above the info threshold + */ + static toStr = m => toStr(m) + /** Clears the prefix cache */ + static clear = () => { + this.#prefixCache.length = 0; + } +} \ No newline at end of file diff --git a/javascript/tagAutocomplete.js b/javascript/tagAutocomplete.js index 7107913..3ea6367 100644 --- a/javascript/tagAutocomplete.js +++ b/javascript/tagAutocomplete.js @@ -713,7 +713,9 @@ function addResultsToList(textArea, results, tagword, resetList) { displayText += `[${translations.get(result.text)}]`; // Print search term bolded in result - itemText.innerHTML = displayText.replace(tagword, `${tagword}`); + //itemText.innerHTML = displayText.replace(tagword, `${tagword}`); + itemText.innerHTML = result.highlightedText || displayText.replace(new RegExp(escapeRegExp(tagword), "ig"), "$&"); + //itemText.innerHTML = displayText.replace(/<mark>(.*)<\/mark>/g, "$1") const splitTypes = [ResultType.wildcardFile, ResultType.yamlWildcard] if (splitTypes.includes(result.type) && itemText.innerHTML.includes("/")) { @@ -1152,19 +1154,19 @@ async function autocomplete(textArea, prompt, fixedTag = null) { results = results.concat(extraResults); } }*/ - let mappedAllTags = allTags.map(t => { - return {text: t[0], cat: t[1], count: t[2], aliases: t[3]}; - }); - const fuzResult = fuzzysort.go(tagword, mappedAllTags, { - key: 'text' - }) - fuzResult.forEach(r => { - let result = new AutocompleteResult(r.target.trim(), ResultType.tag) - result.category = r.obj["cat"]; - result.count = r.obj["count"]; - result.aliases = r.obj["aliases"]; + const fuzResult = TacFuzzy.search(allTags.map(t => t[0]), tagword) + for (let i = 0; i < fuzResult.haystackIndices.length; i++) { + const idx = fuzResult.haystackIndices[i]; + const orderIdx = fuzResult.orderIndices[i]; + const tag = allTags[idx]; + + let result = new AutocompleteResult(tag[0], ResultType.tag) + result.highlightedText = TacFuzzy.toStr(orderIdx) + result.category = tag[1]; + result.count = tag[2]; + result.aliases = tag[3]; results.push(result); - }); + } } // Guard for empty results