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>'
}