2

現在、編集可能な div があり、非常に基本的な構文の強調表示を追加したいと考えています。基本的に、 * の間のテキストを別の色に変え、引用符内のテキストを別の色に変えたいと思っています。例えば:

入力:"hello" *world*

出力:<span class='a'>"hello"</span> <span class='b'>*world*</span>

Rangy.js ライブラリを使用してキャレットの位置を保存および復元しているので、問題はありません。しかし、私は入力を出力に変えるのに本当に苦労しています。私が抱えている大きな問題は、既に強調表示されている " と * を無視することです。

誰かが基本的なアルゴリズムや正規表現などの方向に私を向けることができれば、それは大歓迎です.

4

2 に答える 2

2
function highlight(text) {
    var result = [];
    for (var i = 0; i < text.length; i++) {
        if (text[i] === '"') {
            var stop = text.indexOf('"', i + 1);
            result.push('<span class="a">');
            result.push(text.substring(i, stop+1));
            result.push('</span>');
            i = stop;
        }
        else if (text[i] === '*') {
            var stop = text.indexOf('*', i + 1);
            result.push('<span class="b">');
            result.push(text.substring(i, stop+1));
            result.push('</span>');
            i = stop;
        }
        else if (text[i] === '<') {
            // Skip simple HTML tags.
            var stop = text.indexOf('>', i + 1);
            result.push(text.substring(i, stop+1));
            i = stop;
        }
        else {
            result.push(text.substring(i,i+1));
        }
    }
    return result.join('');
}

例:

>>> highlight('foo *bar"baz"qux* "foobar" qux')
"foo <span class="b">*bar"baz"qux*</span> <span class="a">"foobar"</span> qux"

または正規表現で:

function highlight2(text) {
    return text.replace(/([*"]).*?\1|<[^<>]*>/g, function (match, ch) {
        // 'match' contains the whole match
        // 'ch' contains the first capture-group
        if (ch === '"') {
            return '<span class="a">' + match + '</span>';
        }
        else if (ch === '*') {
            return '<span class="b">' + match + '</span>';
        }
        else {
            return match;
        }
    });
}

正規表現([*"]).*?\1には次が含まれます。

  • [*"]*またはに一致し"ます。(内部でエスケープする必要はありません[ ])。
  • ( )一致した文字列をキャプチャ グループ 1 にキャプチャします。
  • .*?最初まで何でも一致します...
  • \1キャプチャ グループ 1 にキャプチャされたものと同じ文字列に一致します。
  • |「または」です。左辺との一致を試み、それが失敗した場合は右辺との一致を試みます。
  • <[^<>]*>単純な html タグに一致します。<リテラルまたはその中の属性を処理することはできません>: <a href="info.php?tag=<i>">(これはいずれにしても悪い HTML ですが、一部のブラウザーはそれを受け入れます。)

HTML タグに一致する場合、chパラメータは にundefinedなり、else-branch が選択されます。

さらに文字を追加したい場合は、それらを の中に入れ[ ]、if ステートメントを追加してそれらを処理します。を除く任意の文字をエスケープせずに-使用できます。これらの文字を追加するには、それらの前に別の文字を配置する必要があります。\]\

于 2013-06-24T16:45:31.593 に答える
0

あなたの基本的なアルゴリズムは

function highlight(myInput) {
  // Split the string into tokens.
  // "[^"]*"    matches a minimal run surrounded by quotes
  // \*[^*]*\*  matches a minimal run surrounded by asterisks
  // ["*][^"*]* matches an unmatched quote or asterisk and the tail of the string
  // [^"*]+     matches a maximal un-styled run
  var tokens = myInput.match(/"[^"]*"|\*[^*]*\*|["*][^"*]*$|[^"*]+/g);

  // Walk over the list of tokens and turn them into styled HTML
  var htmlOut = [];
  for (var i = 0, n = tokens.length; i < n; ++i) {
    var token = tokens[i];
    // Choose a style.
    var className =
        token.charAt(0) == '"' ? "a" : token.charAt(0) == '*' ? "b" : null;
    // Surround in a span if we have a style.
    if (className) { htmlOut.push("<span class='", className, "'>"); }
    // HTML escape the token content.
    htmlOut.push(token.replace(/&/g, "&amp;").replace(/</g, "&lt;"));
    if (className) { htmlOut.push("</span>"); }
  }
  // Join the output tokens.
  return htmlOut.join('');
}


alert(highlight('"hello" *world*'));
于 2013-06-24T19:53:35.687 に答える