4

こんにちは、innerHTML ブロック内のテキストを置き換える正規表現を見つけて、Google IM と同様の操作でテキストのローカル書式設定を提供しようとしています。

Where: 
_Italics_
!Inderline!
*Bold*
-Strike-

条件の一部として、テキストをシンボルで囲む必要がありますが、直後にスペースが続くとトリガー条件が無効になります。so * bold* は太字になりません and: * 太字ではありませんが、これは太字です

innerHTML には既に href に変換された URL があるため、それらをいじらないように、正規表現の前に次を追加しました。

    (?!(?!.*?<a)[^<]*<\/a>)

次の JavaScript はすべての結果をキャプチャするわけではなく、置換を実行する順序によって結果が異なります。

var boldPattern          = /(?!(?!.*?<a)[^<]*<\/a>)\*([^\s]+[\s\S]?[^\s]+)\*([\s_!-]?)/gi;
var italicsPattern       = /(?!(?!.*?<a)[^<]*<\/a>)_([^\s]+[\s\S]?[^\s]+)_([\s-!\*]?)/gi;
var strikethroughPattern = /(?!(?!.*?<a)[^<]*<\/a>)-([^\s]+[\s\S]?[^\s]+)-([\s_!\*]?)/gi;
var underlinePattern     = /(?!(?!.*?<a)[^<]*<\/a>)!([^\s]+[\s\S]?[^\s]+)!([\s-_\*]?)/gi;
str = str.replace(strikethroughPattern, '<span style="text-decoration:line-through;">$1</span>$2');
str = str.replace(boldPattern, '<span style="font-weight:bold;">$1</span>$2');
str = str.replace(underlinePattern, '<span style="text-decoration:underline;">$1</span>$2');
str = str.replace(italicsPattern, '<span style="font-style:italic;">$1</span>$2');

3 を選択 4 のテスト データは次のようになります。

1 _-*ISB*-_ 2 _-!ISU!-_ 3 _*-IBS-*_ 4 _*!IBU!*_
5 _!-IUS-!_ 6 _!*IUB*!_ 7 -_*SIB*_- 8 -_!SIU!_-
9 -*_SBI_*- 10 -*!SBU!*- 11 -!_SUI_!- 12 -!*SIB*!-
13 *_-BIS-_* 14 *_!BIU!_* 15 *-_BSI_-* 16 *-!BSU!-*
17 *!_BUI_!* 18 *!-BUS-!* 19 !_-UIS-_! 20 !_*UIB*_!
21 !-_USI_-! 22 !-*USB*-! 23 !*_UBI_*! 24 !*-UBS-*!

次のように、4 つのモードすべてが選択されている 24 の順列のいずれかのように、4 レベルの深いネストされたスタイル スパンを使用することもできます。

    -!_*SUIB*_!-

ありがとう、私はこれを約1週間戦ってきました。

innerHTML「マークアップを動的に渡すべきではない」という Mozilla からの悪いフィードバックを回避するためのボーナス ポイント。(フォーマットを変更しているときにそれがどのように可能になるかわかりません)。

百万の正規表現ウィザードに感謝します! 私はあなたの借りがあります。

ムウルフ。

アップデート

上記と同じ href 検出と @talemyn help を使用すると、次のようになります。

var boldPattern          = /(?!(?!.*?<a)[^<]*<\/a>)\*([^\s][^\*]*)\*/gi;
var italicsPattern       = /(?!(?!.*?<a)[^<]*<\/a>)_([^\s][^_]*)_/gi;
var strikethroughPattern = /(?!(?!.*?<a)[^<]*<\/a>)-([^\s][^-]*)-/gi;
var underlinePattern     = /(?!(?!.*?<a)[^<]*<\/a>)!([^\s][^!]*)!/gi;
str = str.replace(strikethroughPattern, '<s>$1</s>');
str = str.replace(italicsPattern, '<span style="font-style:italic;">$1</span>');
str = str.replace(boldPattern, '<strong>$1</strong>');
str = str.replace(underlinePattern, '<u>$1</u>');

極端な例をカバーしているようです:

    _wow *a real* !nice *person! on -stackoverflow* figured- it out_ cool beans.

スタイルスパンを使用して正規表現ルックバックを実行して、以前の閉じられていないスパンを特定し、それを閉じ、古い形式と新しい属性で新しいスパンを開き、想定されたときに閉じて、新しいスパンを開いてフォーマットを完了することができると思います..しかし、それ@NovaDenizen が指摘しているように、正規表現を使用すると、面倒になったり、不可能になったりする可能性があります。

いつもお世話になっております。改善点があれば教えてください。注意: サイトの CSS がレンダリングされないため、使用できませんでした。それは過負荷にできますか?[これは firefox/greasemonkey/chrome プラグイン用です]

更新 (ほぼ) FINAL

@MikeMが正しく述べたように、私の「壊れた」テストフレーズを使用すると、例として、適切にネストされているかどうかに関係なく、Google IMで正しくレンダリングされます(下線を除く)。そのため、Google IM のテキストからの HTML 出力を見ると、文字列が事前にフォーマットされていないことに気付きましたが、必要に応じてシンプルに置き換えられました。

そのため、resetcss を使用して削除していたサイト コードを確認した後、JavaScript を介して CSS フォーマットを挿入する必要がありました。救助へのスタックオーバーフロー。 https://stackoverflow.com/questions/707565/how-do-you-add-css-with-javascripthttps://stackoverflow.com/questions/20107/yui-reset-css-makes-strongemthis-not-work-em-strong

したがって、私のソリューションは次のようになります。

....
var css = document.createElement("style");
css.type = "text/css";
css.innerHTML = "strong, b, strong *, b * { font-weight: bold !important; } \
            em, i, em *, i * { font-style: italic !important; }";
document.body.appendChild(css);
 ....
var boldPattern          = /(?!(?!.*?<a)[^<]*<\/a>)\*([^\s][^\*]*)\*/gi;
var italicsPattern       = /(?!(?!.*?<a)[^<]*<\/a>)_([^\s][^_]*)_/gi;
var strikethroughPattern = /(?!(?!.*?<a)[^<]*<\/a>)-([^\s][^-]*)-/gi;
var underlinePattern     = /(?!(?!.*?<a)[^<]*<\/a>)!([^\s][^!]*)!/gi;
str = str.replace(strikethroughPattern, '<s>$1</s>');
str = str.replace(italicsPattern, '<i>$1</i>');
str = str.replace(boldPattern, '<b>$1</b>');
str = str.replace(underlinePattern, '<u>$1</u>');
.....

そして、tadaそれはほとんど機能します!

UPDATE FINAL SOLUTION @MikeMからのアンカー要素チェックの土壇場での単純化と、別のstackoverflow投稿からの条件の組み合わせの後、完全な実用的なソリューションに到達しました。

また、トリガー トークンを並べて置き換えていたため、終了記号を含む 1 文字スタイルのチェックを追加する必要がありました。

@ acheong87 が \w を含むので注意することを思い出させた_ので、それは取り消し線パターン以外のすべてのラッピング条件に追加されました。

var boldPattern          = /(?![^<]*<\/a>)(^|<.>|[\s\W_])\*(\S.*?\S)\*($|<\/.>|[\s\W_])/g;
var italicsPattern       = /(?![^<]*<\/a>)(^|<.>|[\s\W])_(\S.*?\S)_($|<\/.>|[\s\W])/g;
var strikethroughPattern = /(?![^<]*<\/a>)(^|<.>|[\s\W_])-(\S.*?\S)-($|<\/.>|[\s\W_])/gi;
var underlinePattern     = /(?![^<]*<\/a>)(^|<.>|[\s\W_])!(\S.*?\S)!($|<\/.>|[\s\W_])/gi;
str = str.replace(strikethroughPattern, '$1<s>$2</s>$3');
str = str.replace(italicsPattern, '$1<i>$2</i>$3');
str = str.replace(boldPattern, '$1<b>$2</b>$3');
str = str.replace(underlinePattern, '$1<u>$2</u>$3');

皆さん、どうもありがとうございました (@MikeM、@talemyn、@acheong87 など)。

ムウルフ。

4

3 に答える 3

2

これらを試してください:

var boldPattern          = /\*([^\s][^\*]*)\*/gi;
var italicsPattern       = /_([^\s][^_]*)_/gi;
var strikethroughPattern = /-([^\s][^-]*)-/gi;
var underlinePattern     = /!([^\s][^!]*)!/gi;

ただし、 では、これらの正規表現パターンに 2 番目の一致がないため、 をreplace使用しないでください。$2

于 2013-03-07T18:27:31.263 に答える
1

ネガティブ先読みから内側のネガティブ先読みを削除することをお勧めします。

/(?!(?!.*?<a)[^<]*<\/a>)_it_/.test( ' _it_ <a></a>' );         // true  (correct)
/(?!(?!.*?<a)[^<]*<\/a>)_it_/.test( '<a> _it_ </a>' );         // false (correct)
/(?!(?!.*?<a)[^<]*<\/a>)_it_/.test( '<a> _it_ </a> <a></a>' ); // true  (wrong)

/(?![^<]*<\/a>)_it_/.test( ' _it_ <a></a>' );                  // true  (correct)
/(?![^<]*<\/a>)_it_/.test( '<a> _it_ </a>' );                  // false (correct)
/(?![^<]*<\/a>)_it_/.test( '<a> _it_ </a> <a></a>' );          // false (correct)
于 2013-03-08T11:41:00.387 に答える
1

以下は、誤ってネストされたスパンを作成するべきではありません

var old;
var rx = /(?![^<]*(?:>|<\/a>))([!*_-])((?!\1)[^<>\s][^<>]*?)\1/g;

while ( old != str ) {
    old = str;
    str = str.replace( rx, function ( $0, $1, $2 ) {
        var style = $1 == '!' ? "text-decoration:underline"
                  : $1 == '*' ? "font-weight:bold"
                  : $1 == '_' ? "font-style:italic"
                              : "text-decoration:line-through";

        return  '<span style="' + style + ';">' + $2 + '</span>'
    } );
}

最初に外側の区切り文字を置き換えるため、区切り文字の内側にスパンを挿入しないでください。

リクエストに応じて詳細な説明。

于 2013-03-07T20:11:17.020 に答える