Creating a Highlighter in Vanilla JS

I think thrice in recent past I needed a highlighter while coding. Two times, I used the plugin. Once the jQuery plugin, and the second time, a react plugin. Then when I was creating a filter (by the way, filters are my favourite), I needed the highlighter once more. I opened a new tab in the browser and hit the keywords. I had used a react highlighter a few months ago, so I knew what exactly I needed. I copied the code to install the package from their GitHub page, and just when I was about to hit enter after pasting the clipboard content on the command line, something else hit me.

Why use a plugin?

I asked myself, why do I need to use a plugin for this simple task. Isn’t highlighting is all about splitting the string and then surrounding the matched substring with some styles in a span tag?

I wrote a function within a few minutes, but when I ran it and tested in my actual development, it failed. I checked the algorithm once again and I could see what I was doing wrong.

So one of the key steps of creating a highlighter of this kind is, we need to ignore character cases. Then how do we find the character case-insensitive substring? The regular expression was the answer.

How it works.
Find the case-insensitive match in the given string.
Divide the string using case-insensitive split.
Join the split and matched parts by adding required styles in the matched parts.

Here is the code in Vanilla JS.

/**
 * @description function to convert a simple string into 
 * an HTML element with parts of it highlighted.
 * @params {String} str given string
 * @params {String} query substring which needs to be 
 * highlighted.
 * @returns {HTML Element}
 */
function getHighlightedString (str, query) {
  try {
    var len = str.length;
    if (len) {
      /**
       * 1. create the case-insensitive and global regex.
       * 2. Find the matches.
       * 3. Split the given string.
       * 4. Initialise an empty array.
       */
      let reg = new RegExp (query, "ig"),
          matches = str.match (reg),
          parts = str.split (reg),
          tempStr = [];

      // do the following only if we have parts of string available, and we have found matches.

      if (parts.length && matches && matches.length) {

        /**
         * 1. Push the part of the string into the new array.
         * 2. Create a temp string with required style using the first match.
         * 3. Push the temp string into the new array (i.e. after first part).
         * 4. Repeat till we reach the last part of the string.
         * IMP: Match substrings count will always be one less than the split parts.
         */
        for (let count = 0; count < parts.length; count++) {
          tempStr.push (parts[count])
          if (matches[count]) {
            var temp = "<b class='highlight-class'>" +
                       matches[count] +
                       "</b>";
            tempStr.push (temp);
          }
        }
        // after all parts have been collected, join the array and return
        str = tempStr.join ("");  
      }
    } else {
      throw "Empty String";
    }
    return str;
  } catch (e) {
    console.trace ("Error ", e);
  }
}