HTML Encoding of String 2

Given a string and an array representing the HTML encoding of the string from and to with the given tag. Return the HTML encoded string.

Answer: Hello, World

const encoded = parse("Hello, World", [
  [0, 2, "i"],
  [7, 10, "u"],
  [4, 9, "b"],
  [2, 7, "i"],
  [7, 9, "u"],
]);
console.log(encoded);
// <i>He<i>l</i></i><i>l<b>o, <u><u>W</u></u></b></i><b><u><u>or</u></u></b><u>l</u>d
function Stack() {
  this.items = [];
  this.index = 0;

  this.push = (val) => {
    this.items[this.index] = val;
    this.index += 1;
  };

  this.pop = () => {
    this.index -= 1;
    return this.items[this.index];
  };

  this.peek = () => {
    return this.items[this.index - 1];
  };
}

function Tag(start, end, tag) {
  this.start = start;
  this.end = end;
  this.tag = tag;
  this.text = "";

  this.getRange = () => {
    return this.end - this.start;
  };
}

// Priority Queue
function addAndSort(track, index, tag) {
  if (!track[index]) {
    track[index] = [];
  }
  track[index] = [...track[index], tag];
  track[index].sort((a, b) => a.getRange() - b.getRange());
}

function parse(str, markups) {
  const track = Array(str.length).fill(null);

  for (let markup of markups) {
    const [start, end, tag] = markup;
    addAndSort(track, start, new Tag(start, end, tag));
  }

  const html = new Stack();

  // initilize with a new Tag that has max range and empty string
  html.push(new Tag(0, Number.MAX_VALUE, ""));

  for (let i = 0; i < str.length; i++) {
    while (track[i] && track[i].length > 0) {
      const curr = track[i].shift();
      curr.text = "<" + curr.tag + ">";

      if (curr.end > html.peek().end) {
        const split = new Tag(html.peek().end + 1, curr.end, curr.tag);
        addAndSort(track, html.peek().end + 1, split);
        curr.end = html.peek().end;
      }

      html.push(curr);
    }

    html.peek().text += str[i];

    while (html.peek().end === i) {
      html.peek().text += "</" + html.peek().tag + ">";
      const text = html.pop().text;
      html.peek().text += text;
    }
  }
  return html.pop().text;
}