From 338bed25c19cfded319ba3abfc8b6cce10ca91f0 Mon Sep 17 00:00:00 2001 From: Thomas Wilkerling Date: Mon, 1 Sep 2025 14:14:31 +0200 Subject: [PATCH] highlight boundary always produces preceding ellipsis #508 --- README.md | 1 - dist/flexsearch.bundle.debug.js | 4 +-- dist/flexsearch.bundle.min.js | 4 +-- dist/flexsearch.bundle.module.debug.js | 4 +-- dist/flexsearch.bundle.module.min.js | 4 +-- dist/flexsearch.compact.debug.js | 4 +-- dist/flexsearch.compact.min.js | 4 +-- dist/flexsearch.compact.module.debug.js | 4 +-- dist/flexsearch.compact.module.min.js | 4 +-- dist/flexsearch.es5.debug.js | 4 +-- dist/flexsearch.es5.min.js | 4 +-- dist/flexsearch.light.debug.js | 2 +- dist/flexsearch.light.min.js | 2 +- dist/flexsearch.light.module.debug.js | 2 +- dist/flexsearch.light.module.min.js | 2 +- dist/module-debug/document/highlight.js | 2 +- dist/module-min/document/highlight.js | 2 +- dist/module/document/highlight.js | 2 +- doc/context-index.svg | 10 +++--- package-lock.json | 4 +-- package.json | 6 +--- src/document/highlight.js | 2 +- test/highlight.js | 45 +++++++++++++++++++++++++ 23 files changed, 82 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 88d6b29..9a9b81e 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,6 @@ FlexSearch has been helping developers around the world build powerful, efficien Donate using Github Sponsors Donate using Liberapay Donate using Patreon -Donate using Bountysource Donate using PayPal ### FlexSearch Sponsors diff --git a/dist/flexsearch.bundle.debug.js b/dist/flexsearch.bundle.debug.js index b2d972e..1a49bcd 100644 --- a/dist/flexsearch.bundle.debug.js +++ b/dist/flexsearch.bundle.debug.js @@ -1,5 +1,5 @@ /**! - * FlexSearch.js v0.8.205 (Bundle/Debug) + * FlexSearch.js v0.8.206 (Bundle/Debug) * Author and Copyright: Thomas Wilkerling * Licence: Apache-2.0 * Hosted by Nextapps GmbH @@ -1299,7 +1299,7 @@ function bb(a, c, b, e, d, f, g) { } q = ""; for (let y = 0, J; y < D.length; y++) { - J = (y && G[y] ? " " : (y && !d ? " " : "") + d) + D[y], q += J; + J = (G[y] ? y ? " " : "" : (y && !d ? " " : "") + d) + D[y], q += J; } d && !G[D.length] && (q += d); } diff --git a/dist/flexsearch.bundle.min.js b/dist/flexsearch.bundle.min.js index 87c4fc4..29d1376 100644 --- a/dist/flexsearch.bundle.min.js +++ b/dist/flexsearch.bundle.min.js @@ -1,5 +1,5 @@ /**! - * FlexSearch.js v0.8.205 (Bundle) + * FlexSearch.js v0.8.206 (Bundle) * Author and Copyright: Thomas Wilkerling * Licence: Apache-2.0 * Hosted by Nextapps GmbH @@ -46,7 +46,7 @@ B.replace(da.split,""):B).length-z.length,F="",N=0;for(var O=0;O0&&(E+=t),E<=G)x=r?A-(r>0?r:0):A-((G-E)/2|0),v=t?D+(t>0?t:0):x+G,l||(x>0&&q.charAt(x)!==" "&&q.charAt(x-1)!==" "&&(x=q.indexOf(" ",x),x<0&&(x=0)),v=v.length-1){if(J>= v.length){E[y+1]=1;J>=x.length&&(G[y+1]=1);continue}C-=u}q=v[J].text;if(L=t&&z[y])if(L>0){if(q.length>L)if(E[y+1]=1,l)q=q.substring(0,L);else continue;(L-=q.length)||(L=-1);z[y]=L}else{E[y+1]=1;continue}if(C+q.length+1<=k)q=" "+q,D[y]+=q;else if(l)U=k-C-1,U>0&&(q=" "+q.substring(0,U),D[y]+=q),E[y+1]=1;else{E[y+1]=1;continue}}else{if(E[y])continue;J-=K;if(A[J]){C-=u;E[y]=1;G[y]=1;continue}if(J<=0){if(J<0){E[y]=1;G[y]=1;continue}C-=u}q=v[J].text;if(L=r&&B[y])if(L>0){if(q.length>L)if(E[y]=1,l)q=q.substring(q.length- L);else continue;(L-=q.length)||(L=-1);B[y]=L}else{E[y]=1;continue}if(C+q.length+1<=k)q+=" ",D[y]=q+D[y];else if(l)U=q.length+1-(k-C),U>=0&&U=x.length-1?Qa=1:J0&&(E+=t),E<=G)x=r?A-(r>0?r:0):A-((G-E)/2|0),v=t?D+(t>0?t:0):x+G,l||(x>0&&q.charAt(x)!==" "&&q.charAt(x-1)!==" "&&(x=q.indexOf(" ",x),x<0&&(x=0)),v=v.length-1){if(J>= v.length){E[y+1]=1;J>=x.length&&(G[y+1]=1);continue}C-=u}q=v[J].text;if(L=t&&z[y])if(L>0){if(q.length>L)if(E[y+1]=1,l)q=q.substring(0,L);else continue;(L-=q.length)||(L=-1);z[y]=L}else{E[y+1]=1;continue}if(C+q.length+1<=k)q=" "+q,D[y]+=q;else if(l)U=k-C-1,U>0&&(q=" "+q.substring(0,U),D[y]+=q),E[y+1]=1;else{E[y+1]=1;continue}}else{if(E[y])continue;J-=K;if(A[J]){C-=u;E[y]=1;G[y]=1;continue}if(J<=0){if(J<0){E[y]=1;G[y]=1;continue}C-=u}q=v[J].text;if(L=r&&B[y])if(L>0){if(q.length>L)if(E[y]=1,l)q=q.substring(q.length- L);else continue;(L-=q.length)||(L=-1);B[y]=L}else{E[y]=1;continue}if(C+q.length+1<=k)q+=" ",D[y]=q+D[y];else if(l)U=q.length+1-(k-C),U>=0&&U=x.length-1?Pa=1:J0?u:0):C-((t-y)/2|0),r=p?z+(p>0?p:0):v+t,m||(v>0&&n.charAt(v)!==" "&&n.charAt(v-1)!==" "&&(v=n.indexOf(" ",v),v<0&&(v=0)),r=r.length-1){if(G>=r.length){y[q+1]= 1;G>=v.length&&(t[q+1]=1);continue}F-=x}n=r[G].text;if(H=p&&D[q])if(H>0){if(n.length>H)if(y[q+1]=1,m)n=n.substring(0,H);else continue;(H-=n.length)||(H=-1);D[q]=H}else{y[q+1]=1;continue}if(F+n.length+1<=h)n=" "+n,z[q]+=n;else if(m)O=h-F-1,O>0&&(n=" "+n.substring(0,O),z[q]+=n),y[q+1]=1;else{y[q+1]=1;continue}}else{if(y[q])continue;G-=J;if(C[G]){F-=x;y[q]=1;t[q]=1;continue}if(G<=0){if(G<0){y[q]=1;t[q]=1;continue}F-=x}n=r[G].text;if(H=u&&E[q])if(H>0){if(n.length>H)if(y[q]=1,m)n=n.substring(n.length- H);else continue;(H-=n.length)||(H=-1);E[q]=H}else{y[q]=1;continue}if(F+n.length+1<=h)n+=" ",z[q]=n+z[q];else if(m)O=n.length+1-(h-F),O>=0&&O=v.length-1?ua=1:G0?u:0):C-((t-y)/2|0),r=p?z+(p>0?p:0):v+t,m||(v>0&&n.charAt(v)!==" "&&n.charAt(v-1)!==" "&&(v=n.indexOf(" ",v),v<0&&(v=0)),r=r.length-1){if(G>=r.length){y[q+1]= 1;G>=v.length&&(t[q+1]=1);continue}F-=x}n=r[G].text;if(H=p&&D[q])if(H>0){if(n.length>H)if(y[q+1]=1,m)n=n.substring(0,H);else continue;(H-=n.length)||(H=-1);D[q]=H}else{y[q+1]=1;continue}if(F+n.length+1<=h)n=" "+n,z[q]+=n;else if(m)O=h-F-1,O>0&&(n=" "+n.substring(0,O),z[q]+=n),y[q+1]=1;else{y[q+1]=1;continue}}else{if(y[q])continue;G-=J;if(C[G]){F-=x;y[q]=1;t[q]=1;continue}if(G<=0){if(G<0){y[q]=1;t[q]=1;continue}F-=x}n=r[G].text;if(H=u&&E[q])if(H>0){if(n.length>H)if(y[q]=1,m)n=n.substring(n.length- H);else continue;(H-=n.length)||(H=-1);E[q]=H}else{y[q]=1;continue}if(F+n.length+1<=h)n+=" ",z[q]=n+z[q];else if(m)O=n.length+1-(h-F),O>=0&&O=v.length-1?ta=1:G-1&&(ba=(I?R.substri (x>0&&r.charAt(x)!==" "&&r.charAt(x-1)!==" "&&(x=r.indexOf(" ",x),x<0&&(x=0)),E=E.length-1){if(J>=E.length){F[y+1]=1;J>=x.length&&(G[y+1]=1);continue}O-=n}r=E[J].text;var V=t&&W[y];if(V)if(V> 0){if(r.length>V)if(F[y+1]=1,l)r=r.substring(0,V);else continue;(V-=r.length)||(V=-1);W[y]=V}else{F[y+1]=1;continue}if(O+r.length+1<=k)r=" "+r,N[y]+=r;else if(l)I=k-O-1,I>0&&(r=" "+r.substring(0,I),N[y]+=r),F[y+1]=1;else{F[y+1]=1;continue}}else{if(F[y])continue;J-=L;if(Q[J]){O-=n;F[y]=1;G[y]=1;continue}if(J<=0){if(J<0){F[y]=1;G[y]=1;continue}O-=n}r=E[J].text;if(V=q&&R[y])if(V>0){if(r.length>V)if(F[y]=1,l)r=r.substring(r.length-V);else continue;(V-=r.length)||(V=-1);R[y]=V}else{F[y]=1;continue}if(O+ r.length+1<=k)r+=" ",N[y]=r+N[y];else if(l)I=r.length+1-(k-O),I>=0&&I=x.length-1?I=1:Jw&&(w=i.length+(i?1:0)),x=i.length+(i?1:0)+f.length,y+=a,v.push(u.length),u.push({match:f})),i+=(i?" ":"")+f)}if(!e){const b=d[a];i+=(i?" ":"")+b,l&&u.push({text:b})}else if(l&&y>=l)break}let z=v.length*(f.length-2);if(q||r||l&&i.length-z>l){let a,b,c=l+z-2*s,e=x-w;if(0a&&(a=0))),b=d.length-1?b=1:x=u.length-1){if(x>=u.length){e[y+1]=1,x>=d.length&&(c[y+1]=1);continue}j-=s}i=u[x].text;let f=r&&h[y];if(f)if(0f)if(e[y+1]=1,m)i=i.substring(0,f);else continue;f-=i.length,f||(f=-1),h[y]=f}else{e[y+1]=1;continue}if(j+i.length+1<=l)i=" "+i,a[y]+=i;else if(m){const b=l-j-1;0=x){if(0>x){e[y]=1,c[y]=1;continue}j-=s}i=u[x].text;let d=q&&g[y];if(d)if(0d)if(e[y]=1,m)i=i.substring(i.length-d);else continue;d-=i.length,d||(d=-1),g[y]=d}else{e[y]=1;continue}if(j+i.length+1<=l)i+=" ",a[y]=i+a[y];else if(m){const b=i.length+1-(l-j);0<=b&&bw&&(w=i.length+(i?1:0)),x=i.length+(i?1:0)+f.length,y+=a,v.push(u.length),u.push({match:f})),i+=(i?" ":"")+f)}if(!e){const b=d[a];i+=(i?" ":"")+b,l&&u.push({text:b})}else if(l&&y>=l)break}let z=v.length*(f.length-2);if(q||r||l&&i.length-z>l){let a,b,c=l+z-2*s,e=x-w;if(0a&&(a=0))),b=d.length-1?b=1:x=u.length-1){if(x>=u.length){e[y+1]=1,x>=d.length&&(c[y+1]=1);continue}j-=s}i=u[x].text;let f=r&&h[y];if(f)if(0f)if(e[y+1]=1,m)i=i.substring(0,f);else continue;f-=i.length,f||(f=-1),h[y]=f}else{e[y+1]=1;continue}if(j+i.length+1<=l)i=" "+i,a[y]+=i;else if(m){const b=l-j-1;0=x){if(0>x){e[y]=1,c[y]=1;continue}j-=s}i=u[x].text;let d=q&&g[y];if(d)if(0d)if(e[y]=1,m)i=i.substring(i.length-d);else continue;d-=i.length,d||(d=-1),g[y]=d}else{e[y]=1;continue}if(j+i.length+1<=l)i+=" ",a[y]=i+a[y];else if(m){const b=i.length+1-(l-j);0<=b&&b - Context of Relevance + Context-based Scoring - 2. Context Score + 2. Context (Bidirectional) - 1. Partial Score + 1. Partial Match - 3. Document Score + 3. Document Root + Term 2 diff --git a/package-lock.json b/package-lock.json index ff224c7..248cd14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "flexsearch", - "version": "0.8.205", + "version": "0.8.206", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "flexsearch", - "version": "0.8.205", + "version": "0.8.206", "funding": [ { "type": "github", diff --git a/package.json b/package.json index 3f08e02..bb32bcf 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "public": true, "preferGlobal": false, "name": "flexsearch", - "version": "0.8.205", + "version": "0.8.206", "description": "Next-Generation full-text search library for Browser and Node.js", "homepage": "https://github.com/nextapps-de/flexsearch/", "author": "Thomas Wilkerling", @@ -138,10 +138,6 @@ { "type": "paypal", "url": "https://www.paypal.com/donate/?hosted_button_id=GEVR88FC9BWRW" - }, - { - "type": "bountysource", - "url": "https://salt.bountysource.com/teams/ts-thomas" } ] } diff --git a/src/document/highlight.js b/src/document/highlight.js index 5b12153..8656998 100644 --- a/src/document/highlight.js +++ b/src/document/highlight.js @@ -515,7 +515,7 @@ export function highlight_fields(query, result, index, pluck, config){ str = ""; for(let k = 0, tmp; k < final.length; k++){ - tmp = (k && seamless[k] ? " " : (k && !ellipsis ? " " : "") + ellipsis) + final[k]; + tmp = (seamless[k] ? (k ? " " : "") : (k && !ellipsis ? " " : "") + ellipsis) + final[k]; str += tmp; } if(ellipsis && !seamless[final.length]){ diff --git a/test/highlight.js b/test/highlight.js index 556f77b..e8c4f96 100644 --- a/test/highlight.js +++ b/test/highlight.js @@ -1001,4 +1001,49 @@ if(!build_light) describe("Result Highlighting", function(){ expect(search[0].result.length).to.equal(1); expect(search[0].result[0].highlight).to.equal('Published: April 14, 2025 From bold color choices to intricate patterns, there are many ways to make your springtime holiday decorations stand out from the rest. The Onion shares tips for dyeing Easter eggs.'); }); + + it("Should have been highlighted results properly (#508)", async function(){ + + const index = new Document({ + encoder: Charset.Normalize, + document: { + store: true, + index: [ + { + field: "title", + tokenize: "forward" + }, + { + field: "content", + tokenize: "forward" + } + ], + }, + }); + + await index.addAsync({ + id: 1, + title: "Tips For Decorating Easter Eggs", + content: `Published: April 14, 2025 From bold color choices to intricate patterns, there are many ways to make your springtime holiday decorations stand out from the rest. The Onion shares tips for dyeing Easter eggs.` + }); + + const search = await index.search("h", { + suggest: true, + enrich: true, + highlight: { + template: "$1", + merge: true, + clip: false, + boundary: { + before: 200, + after: 100, + total: 400 + } + } + }); + + expect(search.length).to.equal(1); + expect(search[0].result.length).to.equal(1); + expect(search[0].result[0].highlight).to.equal('Published: April 14, 2025 From bold color choices to intricate patterns, there are many ways to make your springtime holiday decorations stand out from the rest. The Onion shares tips for dyeing Easter eggs.'); + }); });