我需要使用 JavaScript 重新格式化输入 HTML,以便生成的输出 HTML 始终是仅<p>
包含一个或多个节点的节点序列,并且每个节点应仅包含一个节点。<span>
<span>
#text
举个例子,我想转换如下所示的 HTML:
<p style="color:red">This is line #1</p>
<p style="color:blue"><span style="color:yellow"><span style="color:red">This is</span> line #2</span></p>
<p style="color:blue"><span style="color:yellow"><span style="color:green">This is line #3</span></span>
<p style="color:blue"><span style="color:yellow">This is</span><span style="color:red">line #4</span></span></p>
到如下所示的 HTML:
<p style="color:red"><span style="color:red">This is line #1</span></p>
<p style="color:red"><span style="color:red">This is</span><span style="color:yellow"> line #2</span></p>
<p style="color:green"><span style="color:red">This is line #3</span>
<p style="color:yellow"><span style="color:yellow">This is</span><span style="color:red">line #4</span></span></p>
额外的,有点切线的信息:
- 文本位于 TinyMCE 编辑器中。HTML 需要符合这种模式,以使应用程序更可用,并为 PDF 输出引擎提供可用的 HTML(
wkhtmltopdf
如果 HTMl 变得过于复杂,并且嵌套跨度会导致在 TinyMCE 中的编辑不直观,则会出现行高问题) - jQuery 不可用。Prototype.JS 在父文档中可用,
window
但不直接在本文档中。我自己能够将 jQuery 代码重新格式化为纯 JavaScript,但在这种情况下实际上不能使用 jQuery:-(
- 是的,我有现有的代码。这个逻辑显然是非常错误的,以至于现在不值得分享。我现在正在努力改进它,如果我能得到它甚至相当接近,我会分享它,所以它会很有用
- 我真的知道我在做什么!我只是盯着这段代码太久了,所以现在要使用的正确算法正在逃避我……
另外,我仍在使用的已完成一半的非功能性代码,以减少反对票:
function reformatChildNodes(node) {
var n,l,parent;
if(node.nodeName.toLowerCase() == 'p') {
// We are on a root <p> node, make that it has at least one child span node:
if(!node.childNodes.length) {
var newSpan = document.createElement('span');
/* set style on newSpan here */
node.appendChild(newSpan);
}
if(node.childNodes[0].nodeName.toLowerCase() != 'span') {
// First child of the <p> node is not a span, so wrap it in one:
var newSpan = document.createElement('span');
/* set style on newSpan here */
newSpan.appendChild(node.childNodes[0]);
node.appendChild(newSpan);
}
// Now repeat for each child node of the <p> and make sure they are all <span> nodes:
for(n=0;n<node.childNodes.length;++n)
reformatChildNodes(node.childNodes[n]);
} else if(node.nodeName.toLowerCase() == 'span') {
// We are on a <span> node, make that it has only a single #text node
if(!node.childNodes.length) {
// This span has no children! it should be removed...
} else if(node.parentNode.nodeName.toLowerCase() != 'p') {
// We have a <span> that's not a direct child of a <p>, so we need to reformat it:
node.parentNode.parentNode.insertBefore(node, parent);
} else {
for(n=0;n<node.childNodes.length;++n)
reformatChildNodes(node.childNodes[n]);
}
} else if(node.nodeName.toLowerCase() == 'div') {
// This is justa dirty hack for this example, my app calls reformatChildNodes on all nodes
for(n=0;n<node.childNodes.length;++n)
reformatChildNodes(node.childNodes[n]);
}
}