JavaScript highlight substring(s) within string

I have a JavaScript String which looks like this:

From Windows to Linux

With JavaScript, how can I highlight the words From and Linux, via a substring which looks like this:

From Linux

so the string looks like this in the end:

<mark>From</mark> Windows to <mark>Linux</mark>

This is my current implementation of the function to do that job:

  function highlightSearchTerm(string, substring) {
    const regex = new RegExp(`(${substring})`, 'ig');
    return string.replace(regex, '<mark>$1</mark>');
  }

I call it like this:

highlightSearchTerm("From Windows to Linux", "from linux")

It works well, the only thing that is missing is to make it work when the substring has words which are not directly next to each other.

These substrings for instance work:

  • from windows
  • From
  • to Linux

While these don’t (Words are not directly next to each other in the main string):

  • Windows Linux
  • from To
  • Linux from

>Solution :

Short Answer

Call highlightSearchTerm() with a pipe(|) between the terms to achieve the desired output.

Longer Answer

The answer has to deal with how you are building your Regex.

The function

function highlightSearchTerm(string, substring) {
    const regex = new RegExp(`(${substring})`, 'ig');
    return string.replace(regex, '<mark>$1</mark>');
  }

It’s important to understand what the corresponding RegExp object that is created reads like, and how it equates to a form that we would maybe write out directly.

First, if we call

// assume substring = 'hello';
new RegExp(`(${substring})`, 'ig');
// Equivalent: /(hello)/ig;

Notice that the grouped item is looking for the word hello.

Now, if we supply something that has multiple things we want in it, such as hi and you then if we supply them as a single string separated by space, e.g.

const substring = 'hey you';
new RegExp(`(${substring})`,'ig');
// Equivalent: /(hey you)/ig

This will not give us what we want because instead of looking for hey or you, the parser is now looking hey you as a phrase.

However, if we separate those things by a pipe (|) we get

// assume substring = 'hey|you';
new RegExp(`(${substring})`,'ig');
// Equivalent: /(hey|you)/ig

This now looks for either hey or you in the string. This is because the pipe character in RegEx is the OR.

If you’d like to expand the search for multiple phrases, you separate each specific one by a pipe, e.g.

new RegExp('(hey|you|that guy)', 'ig');

Will search for the words hey and you and the phrase (space included) that guy.

Leave a Reply