JSFiddle - React, Tailwind, and code Playground

by brigand

HTML

<div id="root">
  <p>
    line1
  </p>
  <p>
    li<b><span class="highlight highlight_9kggk2nfhxfk9urqsks">ne</span></b><span class="highlight highlight_9kggk2nfhxfk9urqsks">2
    </span></p><span class="highlight highlight_9kggk2nfhxfk9urqsks">
  </span><span><span class="highlight highlight_9kggk2nfhxfk9urqsks"><span class="highlight highlight_4b7thakeve2k9urqusd">line3</span></span></span><span class="highlight highlight_9kggk2nfhxfk9urqsks">
  </span>
  <p><span class="highlight highlight_9kggk2nfhxfk9urqsks">
      line4
    </span></p><span class="highlight highlight_9kggk2nfhxfk9urqsks">
  </span><span><span class="highlight highlight_9kggk2nfhxfk9urqsks">line5</span></span>
  <p>
    line6
  </p>
  <span>line7</span>
  <table style="width:100%">
    <tbody>
      <tr>
        <th>Firstname</th>
        <th>Lastname</th>
        <th>Age</th>
      </tr>
      <tr>
        <td>Jill</td>
        <td>Smith</td>
        <td>50</td>
      </tr>
      <tr>
        <td>Eve</td>
        <td>Jackson</td>
        <td>94</td>
      </tr>
    </tbody>
  </table>
</div>

<h2>spans</h2>
<ul id="list"></ul>

<h2>spans json</h2>
<pre id="out"></pre>

CSS

.highlight {
  background: yellow;
}

JavaScript

function textLen(node) {
	if (node.nodeType === Node.TEXT_NODE) {
  	return node.nodeValue.length;
  } else {
	  return 0;
  }
}

function getSpans(root) {
	const spans = [];
	let offset = 0;
  
  function inner(el) {
	  let current = null;
    
  	if (el.classList && el.classList.contains('highlight')) {
			current = [offset];
    }
    
    offset += textLen(el);
    
		for (const child of el.childNodes) {
  		inner(child);
  	}
    
    if (current) {
		  spans.push({ start: current[0], end: offset })  
    }
  }
  
  
  inner(root);
  
  return spans;
}

const result = getSpans(root)
out.textContent = JSON.stringify(result, null, 2)

for (const span of result) {
	list.innerHTML += '<li><pre>' + root.textContent.slice(span.start, span.end) + '</pre></li>'
}