1

正規表現を使用して、独自の html5 RTE で生成されたコードをクリーンアップしようとしています。周りを検索すると、HTMLの解析に正規表現を使用すべきではないと言っている人がたくさんいます...しかし、私はこのクライアント側でJavaScriptを使用しています。正規表現以外のオプションはありますか?

私は後読みを使用しようとしていますが (それらについて知ったばかりです)、JavaScript では動作しないようです。私がしたいのは、<p> の最後にあるすべての <br> を削除することですが、<p><br></p> のように段落内の唯一の要素である <br> は削除しません。そう:

<p>Blah<br><br><br></p> becomes <p>Blah</p>
<p><br></p> stays the same.

これまでのところ、私は持っているだけです

html = html.replace(/(?:<br\s?\/?>)+(<\/p>)/g, '$1');

<br> の数に関係なく、段落の末尾にあるすべての <br> を削除します。

次のようなものが欲しい

html = html.replace(/(?<!<p>)(?:<br\s?\/?>)+(<\/p>)/g, '$1');

編集:私は contenteditable div を使用して、ユーザーがテキストを変更するたびに動的に作成される非常に単純な RTE を作成しています。基本的に、冗長なスパン、br、および p タグなどをクリアするだけです。

4

5 に答える 5

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>

こちらをご覧ください。

免責事項:私はそれを片付けませんでした。後で戻ってきます。

于 2013-01-13T23:26:52.990 に答える
2

そうです、正規表現を使用して HTML を解析することはできませ

はい、他のオプションがあります。もともと Node を対象としていた、寛容な HTML 解析 JS ライブラリがいくつかありますが、ブラウザで動作するはずです。

また、ブラウザーに HTML パーサーが組み込まれているという事実を利用して、それを使用して HTML を解析することもできます。ADocumentFragmentは、この状況で使用できます。または、あなたの場合、contenteditable要素の DOM を変更するだけです。

于 2013-01-13T22:40:05.250 に答える
0

これは非常に複雑に思えます。次のようなもっと簡単なことを試しましたか?

<p>.+(<br>)+<\/p>

これは<br>、段落の最後(終了タグの直前)で段落内に囲まれ、それ自体と開始タグの間に何かがあるものと一致する必要があります。スペースを有効なものとして受け入れないように変更する必要がありますが、アイデアは得られます。

于 2013-01-13T22:47:50.763 に答える
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.

http://jsfiddle.net/nnH4G/

この方法が正規表現を使用するよりも優れている理由:

  1. あなたがしていることははるかに明白です。あなたや他の開発者が後でこれに戻ってきたときに、「正規表現はいったい何をするのだろ%&^@!£%*cthulu&GJHS^&@う?」と考える必要はありません。

  2. 拡張/変更が容易です。要件がもう少し複雑な場合、(JavaScript の) 正規表現でこれを達成することは文字通り不可能になります。これは、正規表現と HTML がチョムスキー階層内で相対的に位置付けられているためです。

  3. あなたのコードを見た人は、あなたがかなりクールな人だと思うでしょう。

他の回答が指摘しているように、jQueryは決してこれを行う唯一の方法ではありません。しかし、それがクライアント側でどれほどユビキタスであるかを考えると、非常に便利なツールです。

于 2013-01-14T20:17:14.133 に答える
0

正規表現ソリューション(DOM解析でこれを使用することを提案しているわけではありません):

あなたの質問からは、たとえば、何をしたいのかわからない
'<p><br><br></p>'ので、以下に2つの解決策があります。

そのままにしておきたい場合は、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>  
于 2013-01-14T22:49:38.303 に答える