使用javascript进行简单的语法高亮显示

时间:2013-06-24 16:34:47

标签: javascript string parsing

目前我有一个可编辑的div,我想添加非常基本的语法高亮显示。基本上我想要*之间的文字转换不同的颜色和引号中的文字以转换不同的颜色。例如:

输入:"hello" *world*

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

我使用Rangy.js库来保存和恢复插入位置,因此那里没有问题。但是,我真的很难将输入转换为输出。我遇到的一个大问题是忽视任何&#34;和*已经突出显示。

如果有人能指出基本算法或正则表达式的方向,那么我将非常感激。

2 个答案:

答案 0 :(得分:1)

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包含以下内容:

  • [*"]匹配*"。 (它们不需要在[ ]内转义。)
  • ( )将匹配的字符串捕获到capture-group 1。
  • .*?匹配任何内容直到第一个......
  • \1匹配捕获到捕获组1中的相同字符串。
  • |是“或”。它试图匹配左侧,如果失败,它会尝试匹配右侧。
  • <[^<>]*>匹配简单的html标记。它无法处理文字<>中的属性:<a href="info.php?tag=<i>">(无论如何这都是糟糕的HTML,但有些浏览器会接受它。)

如果匹配HTML标记,ch参数将为undefined,并且else - 分支将被选中。

如果要添加更多字符,只需将它们放在[ ]中,然后添加if语句来处理它们。您可以使用除-\]之外的任何字符,而无需转义它们。要添加这些字符,您需要在其前面放置另一个\

答案 1 :(得分: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*'));