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-tags。它将无法处理带有文字<>其中的属性:(<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 回答