# How to Implement Result Highlighting with Customizable Boundaries and Ellipsis in FlexSearch

> Learn to implement result highlighting in FlexSearch with custom boundaries and ellipsis. Control clipping and display for enhanced search results. Get started now.

- Repository: [Nextapps GmbH/flexsearch](https://github.com/nextapps-de/flexsearch)
- Tags: how-to-guide
- Published: 2026-02-23

---

**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`](https://github.com/nextapps-de/flexsearch/blob/main/src/document/highlight.js) and is driven by the `HighlightOptions` type defined in [`src/type.js`](https://github.com/nextapps-de/flexsearch/blob/main/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`](https://github.com/nextapps-de/flexsearch/blob/main/src/document/highlight.js). This routine processes search results by:

1. **Parsing templates** to extract opening and closing markup surrounding the `$1` placeholder (lines 42-52)
2. **Recording match positions** to track where terms appear in the original text
3. **Applying boundary constraints** to limit snippet length using either numeric values or `HighlightBoundaryOptions` objects
4. **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`](https://github.com/nextapps-de/flexsearch/blob/main/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`, and `total` properties

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**: `false` removes ellipsis entirely
- **HighlightEllipsisOptions object**: Custom template with `template` (containing `$1`) and `pattern` properties 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:

```javascript
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:

```javascript
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:

```javascript
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:

```javascript
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:

```javascript
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 `highlight` option to `index.search()`, either as a template string or full `HighlightOptions` object.
- **Control snippet length** using the `boundary` property with numeric values or `HighlightBoundaryOptions` objects containing `before`, `after`, and `total` constraints.
- **Manage truncation** with the `clip` boolean and customize or remove ellipsis using the `ellipsis` property (string, boolean, or `HighlightEllipsisOptions` object).
- **Merge adjacent matches** by setting `merge: true` to produce cleaner, consolidated highlight blocks.
- **Reference implementation** in [`src/document/highlight.js`](https://github.com/nextapps-de/flexsearch/blob/main/src/document/highlight.js) handles 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.