HTML Flatten

by Imabot

HTML

<button id="flat">Flat HTML</button>

<div contenteditable="true" id="editor-container"><h3>HTML flattener</h3><hr><p>Each row of the output array is an object composed of:</p><ul><li><b>index:</b> index from the root node</li><li><b>length:</b> length of the leaf</li><li><b>parents:</b> list of parents to the root node</li></ul><br><p>⬆ a &lt;br&gt; tag.</p></div>

<small>More info on <a href="https://lucidar.me/en/rich-content-editor/flatten-html/">my blog</a></small>

CSS

#editor-container {
	white-space: pre-wrap;
	border:1px solid;
}

JavaScript

let editor = document.getElementById('editor-container');
	
// When the page is ready
document.addEventListener("DOMContentLoaded", () => {
	editor.focus();	
	console.log (flattenHtml(editor));
	console.log (editor.innerText);
})

document.getElementById('flat').onclick = () => { console.log (flattenHtml(editor)); }


// Convert nested HTML info flatten array
function flattenHtml (node, flat=[], tagsList = [])
{
	// Add the current tag
	tagsList.push(node)

	// Check if it is a leaf or not
	if (!node.childNodes.length)
	{
		// Calculate the node index
		let index = (flat[flat.length -1] === undefined) ? 0 : flat[flat.length -1].index + flat[flat.length -1].length;
		// Push the node in the array
		flat.push( { index: index, length: node.length ?? 1, text: node.wholeText ?? '', parents: [...tagsList] });
	}
	else
	{
		// Call the function recursively on each child
		node.childNodes.forEach((child) => { flat = flattenHtml(child, flat, tagsList); })
	}
	// Remove the current tag
	tagsList.splice(tagsList.indexOf(node),1);	
	return flat;
}