How to Implement Result Highlighting with Customizable Boundaries and Ellipsis in FlexSearch
To implement result highlighting in FlexSearch, pass a highlight option to your search query containing a template string or a HighlightOptions object that configures boundaries, ellipsis, and clipping behavior.
FlexSearch provides a powerful highlighting engine that enriches search results with contextual snippets of the original text. According to the nextapps-de/flexsearch source code, the highlighting system lives in src/document/highlight.js and is driven by the HighlightOptions type defined in src/type.js. This implementation allows you to control exactly how much text surrounds each match, how overlaps are handled, and how truncation is indicated.
Understanding the Highlighting Engine
The core highlighting logic resides in the highlight_fields function within src/document/highlight.js. This routine processes search results by:
- Parsing templates to extract opening and closing markup surrounding the
$1placeholder (lines 42-52) - Recording match positions to track where terms appear in the original text
- Applying boundary constraints to limit snippet length using either numeric values or
HighlightBoundaryOptionsobjects - Inserting ellipsis at truncation points with customizable strings or markup templates
The engine automatically activates when a search request contains a highlight option and the index supports document storage (SUPPORT_STORE) and highlighting (SUPPORT_HIGHLIGHTING).
Configuring Highlight Options
The HighlightOptions type (defined in src/type.js lines 299-304) provides granular control over snippet generation.
Template Configuration
The template property defines the markup wrapped around matched terms. It must contain $1 where the matched text should appear:
- Simple:
"<b>$1</b>" - With CSS classes:
"<mark class='highlight'>$1</mark>"
Boundary Control with HighlightBoundaryOptions
The boundary property limits how much context appears around matches. It accepts:
- Number: Total character count (default is
9e5, effectively unlimited) - HighlightBoundaryOptions object: Fine-grained control with
before,after, andtotalproperties
When clip is true (default), the snippet is trimmed to respect boundary limits. When false, the original text is preserved and ellipsis is added only at the edges.
Ellipsis Customization
The ellipsis property controls truncation indicators:
- String: Custom text (default is
"...") - Boolean:
falseremoves ellipsis entirely - HighlightEllipsisOptions object: Custom template with
template(containing$1) andpatternproperties for advanced markup
Merging Consecutive Matches
Set merge: true to collapse adjacent highlighted fragments into a single block. This produces cleaner output when multiple search terms appear close together by replacing consecutive markup blocks with a single space.
Practical Implementation Examples
Basic Template Highlighting
Enable highlighting with a simple string template when searching a Document index:
const index = new Document({
document: {
store: true,
index: [{ field: "title", tokenize: "forward" }]
}
});
index.add({ id: 1, title: "Carmencita" });
index.add({ id: 2, title: "Le clown et ses chiens" });
const result = index.search({
query: "karmen or clown",
enrich: true,
highlight: "<b>$1</b>"
});
// Result contains highlighted snippets:
// { id: 1, doc: {...}, highlight: "<b>Carmen</b>cita" }
// { id: 2, doc: {...}, highlight: "Le <b>clown</b> et ses chiens" }
Custom Boundaries and Clipping
Limit snippet length to 80 characters with automatic clipping:
const result = index.search({
query: "sit amet",
pluck: "title",
highlight: {
template: "<b>$1</b>",
boundary: 80,
clip: true
}
});
Each result will contain at most 80 characters, with ellipsis automatically added on both sides when content is truncated.
Custom Ellipsis Markup
Apply custom styling to truncation indicators:
const result = index.search({
query: "sit amet",
pluck: "title",
highlight: {
template: "<b>$1</b>",
boundary: 32,
ellipsis: {
template: "<i>$1</i>",
pattern: "..."
},
clip: true
}
});
This produces output like: <i>...</i><b>sit</b> <b>amet</b>, con<b>set</b>etur<i>...</i>.
Merged Highlight Blocks
Combine adjacent matches into single highlighted regions:
const result = index.search({
query: "karmen or clown",
enrich: true,
merge: true,
highlight: "<b>$1</b>"
});
When multiple terms appear consecutively, they merge into one continuous <b> block rather than separate markup instances.
Fine-Grained Boundary Control
Use HighlightBoundaryOptions for precise control over context windows:
const result = index.search({
query: "akusam",
enrich: true,
highlight: {
template: "<b>$1</b>",
boundary: { before: 5, after: 5, total: 50 },
clip: true,
ellipsis: false
}
});
This configuration shows exactly 5 characters before and after each match while keeping the total snippet under 50 characters, with no ellipsis markers.
Summary
- Enable highlighting by passing a
highlightoption toindex.search(), either as a template string or fullHighlightOptionsobject. - Control snippet length using the
boundaryproperty with numeric values orHighlightBoundaryOptionsobjects containingbefore,after, andtotalconstraints. - Manage truncation with the
clipboolean and customize or remove ellipsis using theellipsisproperty (string, boolean, orHighlightEllipsisOptionsobject). - Merge adjacent matches by setting
merge: trueto produce cleaner, consolidated highlight blocks. - Reference implementation in
src/document/highlight.jshandles template parsing, boundary calculations, and ellipsis insertion automatically when document storage and highlighting support are enabled.
Frequently Asked Questions
How do I remove the ellipsis entirely from highlighted snippets?
Set the ellipsis property to false in your HighlightOptions configuration. This prevents the engine from inserting any truncation markers, even when content exceeds the specified boundary limits.
What is the difference between clip: true and clip: false in FlexSearch highlighting?
When clip is true (the default), the snippet is trimmed to strictly respect the boundary limits, with ellipsis added where text is removed. When clip is false, the original text is preserved and ellipsis is only added at the beginning or end of the snippet if the content extends beyond the boundary window.
Can I use different boundary lengths for text before and after the matched term?
Yes, pass a HighlightBoundaryOptions object to the boundary property instead of a number. Specify before for characters preceding the match, after for characters following it, and optionally total to constrain the overall snippet length regardless of individual match positions.
Where does FlexSearch store the highlighted output in the search results?
When highlighting is enabled, the engine stores the processed snippet in the highlight property of each result object. If you use enrich: true, this appears alongside the doc property containing the full document; otherwise, it appears in the standard result structure returned by the search method.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →