HTML Line Controller in Javascript

HTML

<div id="container">Lorem ipsum <a href="#">dolor</a> sit amet
<div>Consectetur adipisicing elit, sed do </div> eiusmod tempor
incididunt ut labore et dolore magna aliqua.
</div>

CSS

p { padding: 4px; margin: 4px; border: 1px solid red; }
div { padding: 4px; margin: 4px; border: 1px solid blue; }

JavaScript

function paragraphify(parent) {
	var i, str, p, workspace = document.createElement('div'), nodes = parent.childNodes;

	p = document.createElement('p');
	workspace.appendChild(p);

	// Filter nodes out of parent and into the workspace.
	while(nodes.length > 0) {
		// Get the first child node of the parent element.
		node = nodes[0];

		// Divs and paragraphs need not be processed; skip them.
		if(node.nodeName === 'P' || node.nodeName === 'DIV') {
			workspace.insertBefore(node, p);
			continue;
		}

		// Drop the node into the paragraph.
		p.appendChild(node);

		// Skip non-text nodes.
		if(node.nodeName !== '#text') { continue; }

		// We need to parse the text of the node for newlines.
		str = node.nodeValue;
		for(i = 0; i < str.length; i += 1) {
			if(str[i] === '\n') {
				// If text contains a newline ...

				if(i < (str.length - 1)) {
					// ... and there's enough space to split it, then split it.
					parent.insertBefore(document.createTextNode(str.substr(i+1)), nodes[0]);
					node.nodeValue = str.substr(0, i+1);
				}

				// Create a new paragraph for holding elements, and add it to the workspace.
				p = document.createElement('p');
				workspace.appendChild(p);

				// Break here to return to the node-processing loop.
				// If the text was split on a newline, then that will be the next node to be processed.
				break;
			}
		}
	}

	// Pull the nodes back out of the workspace and into the parent element.
	nodes = workspace.children;
	while(nodes.length > 0) {
		node = nodes[0];

		// Skip empty paragraphs.
		if(node.nodeName === 'P' && node.textContent.replace(/\s/g, '').length === 0) {
			workspace.removeChild(node);
		}
		else {
			parent.appendChild(node);
		}
	}
}

paragraphify(document.getElementById('container'));