JavaScript を使用して入力 HTML を再フォーマットし、結果の出力 HTML が常に1 つ以上のノードのみ<p>
を含む一連のノードになり、各ノードに正確に 1 つのノードが含まれるようにする必要があります。<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]);
}
}