我试图使用正则表达式来清理我自己的html5 RTE中生成的一些代码。搜索周围我看到很多人说正则表达式不应该被用来解析HTML ...但是我用JavaScript做了这个客户端。除了正则表达式,我还有其他选择吗?
我一直在尝试使用lookbehinds(刚刚发现它们),但它们似乎不适用于JavaScript。我想要做的是删除所有< br>在< p>的最后,但不是段落中唯一的元素,例如< p>< br>< / p>。所以:
<p>Blah<br><br><br></p> becomes <p>Blah</p>
<p><br></p> stays the same.
到目前为止我只有
html = html.replace(/(?:<br\s?\/?>)+(<\/p>)/g, '$1');
无论有多少,都会删除段落末尾的所有&lt; br&gt;。
我想要像
这样的东西html = html.replace(/(?<!<p>)(?:<br\s?\/?>)+(<\/p>)/g, '$1');
编辑:我使用contenteditable div来创建一个非常简单的RTE,每当用户想要更改某些文本时,它就会动态创建。基本上只是清除reduntant span,br和p标签等。
答案 0 :(得分:3)
使用DOM解析器。
我们的想法是保留所有连续的<br>
元素。每次出现非空文本元素或任何其他元素时擦除数组。
如果在循环结束时有<br>
列表,则将其删除。这些是尾随的<br>
元素。
var $pp = document.getElementsByTagName("p");
for(var i = 0, $p = $pp[0], $br = [], alone = true; i < $pp.length; i = i + 1, $p = $pp[i], $br = [], alone = true){
for(var j = 0, $child = $p.childNodes[0]; j < $p.childNodes.length; j = j + 1, $child = $p.childNodes[j]){
if(($child.tagName !== "BR") && ($child.textContent.trim() !== "")){
alone = false;
$br = [];
} else {
$br.push($child);
}
}
for(var j = 0; j < $br.length - alone; j = j + 1){
$p.removeChild($br[j]);
}
}
例如,
<p>Foo<br><br><br></p>
<p>Foo<br>Bar<br><br></p>
<p><br></p>
变为
<p>Foo</p>
<p>Foo<br>Bar</p>
<p><br></p>
免责声明:我没有清理它。我稍后会再回来。
答案 1 :(得分:2)
你是对的,你can't使用正则表达式来解析HTML,因为他们无法这样做。
是的,您还有其他选择。有几个宽容的HTML解析JS库最初定位到Node,但应该在浏览器中工作。
您还可以利用浏览器具有内置HTML解析器的事实,并使用它来解析您的HTML。在这种情况下可能会使用DocumentFragment
。或者,在您的情况下,您只需修改contenteditable
元素中的DOM。
答案 2 :(得分:0)
这似乎过于复杂。你有没有尝试过更简单的东西:
<p>.+(<br>)+<\/p>
这应该匹配段落中包含的任何<br>
,在它的最末端(在结束标记之前)并且在它自己和开始标记之间有一些东西。你可能应该改变它,所以它不接受空格作为有效的东西,但你明白了。
答案 3 :(得分:0)
这里有几行jQuery:
// Note: in order to load the html into the dom it needs a root. I'm using `div`:
var input = '<div>' +
'<p>Blah<br><br><br></p> becomes <p>Blah</p>' +
'<p><br></p> stays the same.' +
'</div>';
// Load the html into a jQuery object:
var $html = $(input);
// Get all the `<br>`s at the end of `p`s that are not the only-child:
var $lastBreaks = $html.find('p>:last-child:not(:only-child)').filter('br');
// Remove any immediately preceding `br`s:
$lastBreaks.prevUntil(':not(br)').remove();
// Remove the last `br`s themselves
$lastBreaks.remove();
// Output:
console.log($html.html());
输出:
<p>Blah</p> becomes <p>Blah</p><p><br></p> stays the same.
这种方法比使用正则表达式更好的原因:
你正在做的事情更加明显。当您或其他开发人员稍后回到此处时,您将不必考虑“正则表达式%&^@!£%*cthulu&GJHS^&@
到底做了什么?”
扩展/修改更容易。如果你的要求甚至稍微复杂一点,用(JavaScript)的正则表达式because of Regex and HTMLs relative positions in the Chomsky hierarchy实现这一点几乎是不可能的。
看到你的代码的人会觉得你一般都很酷。
jQuery绝不是唯一的方式,正如其他答案所指出的那样。但鉴于它在客户端无处不在,它是一个非常有用的工具。
答案 4 :(得分:0)
正则表达式解决方案(不是我建议你应该使用它来解析DOM):
我从你的问题中不清楚你想要发生什么,例如,
'<p><br><br></p>'
,所以下面有两个解决方案。
如果您希望保持原样,可以使用1)如果您希望它变为'<p></p>'
,您可以使用2):
<强> 1)强>
html = html.replace(
/<p>([\s\S]+?)(?:<br>)+<\/p>/g,
function ( $0, $1 ) { return $1 == '<br>' ? $0 : '<p>' + $1 + '</p>' }
)
测试
function test(html) {
return html.replace(
/<p>([\s\S]+?)(?:<br>)+<\/p>/g,
function ( $0, $1 ) { return $1 == '<br>' ? $0 : '<p>' + $1 + '</p>' }
)
}
test( '<p>Blah</p>' ); // <p>Blah</p>
test( '<p>Blah<br><br><br></p>' ); // <p>Blah</p>
test( '<p><br>Blah<br></p>' ); // <p><br>Blah</p>
test( '<p><br></p>' ); // <p><br></p>
test( '<p><br><br></p>' ); // <p><br><br></p>
<强> 2)强>
html = html.replace( /(?:([^>]|[^pb]>)(?:<br>)+|(?:<br>){2,})<\/p>/g, '$1</p>' );
测试
function test(html) {
return html.replace( /(?:([^>]|[^pb]>)(?:<br>)+|(?:<br>){2,})<\/p>/g, '$1</p>' );
}
test( '<p>Blah</p>' ); // <p>Blah</p>
test( '<p>Blah<br><br><br></p>' ); // <p>Blah</p>
test( '<p><br>Blah<br></p>' ); // <p><br>Blah</p>
test( '<p><br></p>' ); // <p><br></p>
test( '<p><br><br></p>' ); // <p></p>