flexsearch
flexsearch copied to clipboard
Result highlighting
Perhaps this is a question, if so I couldn't find anything in the documentation searching for "highlighting" or "highlight".
In the awesome auto-complete demo you can type in marblles
and it finds ...All the Marbles
What I'd love to be able to do is display:
<div class="search-result">
...All the <mark>Marbles</mark>
</div>
If it wasn't for the smarts within FlexSearch I could achieve this with a simple regex. Or, if the result object from a search could give me the clues (i.e. that the word "Marbles" matched the input "marblles") then I could use that to do a simple regex.
@ts-thomas I've now written a simple highlighter based on splitting the search string and the string matched. It looks like this:
But the results match Embed
if I "typoed" embbed
too. But then, my regex solution breaks:
If only Flexsearch could have returned, as part of the result, a clue that "embbed" maps to "embed". I.e. "These are the results and they assumed the following map {"embbed": "embed"}". Then I could use that mapping to do my highlighting based on the values of that map. Would that be possible?
Peter can you please share your code? I'm also looking for an highlighter.
You can easily use regex to wrap the matching keyword with an tag for example and highlight using background-color: yellow. For example:
const keyword = 'audio';
const content = '<audio>: The Embed Audio element'
// Make sure there's no regex special chars
const sanitizedKeyword = keyword.replace(/\W/g, '');
// Build regex
const regexForContent = new RegExp(sanitizedKeyword, 'gi');
// Replace content where regex matches
content = content.replace(regexForContent, '<em>$&</em>');
// Content would be
<<em>audio</em>>: The Embed <em>Audio</em> element
I probably found a way to extend the new language processing pipeline to give support for custom "wrap". At least it would be the best place to apply these logic without storing additional data/marker within the index.
Would be awesome to get matching indices or at least strings in response to build up a highlighter.
Do we have an example of how to use such pipelines?
The issue with @SystemR's solution is that you cannot use such a simple search & replace when you have html tags in your content.
For example, when your content is What is <strong>going</strong> on here?
an your keyword is on
, you will end up with What is <str<em>on</em>g>going</str<em>on</em>g> <em>on</em> here?
.
I would suggest to use something like mark.js. It's super easy, for example with the jQuery plugin:
$(".content").unmark({
done: function() {
$(".content").mark(keyword);
}
});
I probably found a way to extend the new language processing pipeline to give support for custom "wrap". At least it would be the best place to apply these logic without storing additional data/marker within the index.
@ts-thomas The way some other libraries (like lunr.js and fuse.js) achieve this is by returning the index of the beginning and then the end of the match (which you usually need to whitelist when building the index). This gives more flexibility with what you want to do with that information than the wrap
.
This is currently the only thing that is preventing us from moving our projects' search to flexsearch, as our indexes are huge docstrings, which we need to trim. The lib is all we need when it comes to speed + memory usage (as well as being maintained :sweat_smile:)
If you could point me in the right direction, I could try and implement it with my limited JS knowledge :)
I probably found a way to extend the new language processing pipeline to give support for custom "wrap". At least it would be the best place to apply these logic without storing additional data/marker within the index.
Hi @ts-thomas ! Thank you sooooo much for your work on 0.7.0. I'm eager to explore it more. But do you think there's a connection with solving this issue using 0.7.0?
Just want to give my +1 here.
Using mark.js did work for me, but it feels like a workaround, because it can only mark already created DOM elements. It would be better to already know where and how to highlight, then you can create the DOM elements with tags already included.
If the search results already contain the matches (like in fuse.js) I imagine that the performance could be much better.
Well, an integrated solution would definitely be the best.
I agree this would be very useful
FYI here's the workaround I'm using on Beekeeper Studio using regexes:
const regex = new RegExp(this.searchTerm.split(/\s+/).filter((i) => i?.length).join("|"), 'gi')
const result = text.replace(regex, (match) => `<strong>${match}</strong>`)
It works great!
I probably found a way to extend the new language processing pipeline to give support for custom "wrap". At least it would be the best place to apply these logic without storing additional data/marker within the index.
Hi @ts-thomas Now that 0.7.x is out. Is there any news on this front?
You mentioned "custom wrap" but I see no mention of it in the README.
To step back a bit, in the original post of this issue, I mentioned it would be nice to get find out which words, after suggestion-correction, were matched. I.e. I searched for marblles
and it matched on Marbles
.
What about the simpler case. If I searched for SEARCH
and a document is matched because it contain this is a search solution
. Here it would be nice know that it matched on line 1, column 1-16.
Or, if I use the OR operator and someone searched for SEARCH BLABLA
it would be nice that SEARCH
matched something but BLABLA
didn't.
Any further news?