首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >语法高亮设计

语法高亮设计
EN

Stack Overflow用户
提问于 2010-11-22 22:34:21
回答 1查看 246关注 0票数 0

为了好玩,我正在用javascript编写我自己的语法高亮笔,并看到了几种方法,但它们都有一些我无法理解的优点和相当严重的缺点。你们对这些方法有什么看法?还有更好的方法吗?

假设

突出显示的

代码存在于单个字符串中。

逼近

  1. 处理其字符串形式中的代码,并使用正则表达式查找模式。

Pros

易于定义和搜索模式

Cons

很难忽略引号或注释中的关键字,

  • 通过空格和换行来拆分字符串,并在数组上循环。

Pros

易于跟踪范围

Cons

很难跟踪拆分之后的空格和换行

编辑:词汇分析

所以,如果我理解的话,使用词法分析,你可以把字符串分解成记号。这听起来很像第二种方法?如何将令牌重新组装到原始字符串中?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-11-23 21:07:25

注意:这使用jQuery。如果您愿意,可以很好地重写它以使用直接的javascript。

实际上,我写了一个小插件来取乐,这样做:

代码语言:javascript
复制
(function($) {
 $.fn.codeBlock = function(blockComment) {

  // Setup keyword regex
   var keywords = /(abstract|boolean|break|byte|case|catch|char|class|const|continue|debugger|default|delete|do|double|else|enum|export|extends|final|finally|float|for|function|goto|if|implements|import|in|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|super|switch|synchronized|this|throw|throws|transient|try|typeof|var|void|volatile|while|with|true|false|prototype)(?!\w|=)/gi;

  // Booleans to toggle comment, regex, quote exclusions
   var comment = false;
   var quote = false;
   var regex = false;

  /*  Array used to store values of regular expressions, quotes, etc.
   so they can be used to ID locations to be skipped durring keyword
   regexing.
  */
   var locator = new Array();
   var locatorIndex = 0;

   if (blockComment) locator[locatorIndex++] = 0;

  var text = $(this).html();
  var continuation;
  var numerals = /[0-9]/;

  var arr = ($(this).html()).split("");
  var outhtml = "";

  for (key in arr) {
   // Assign three variables common 'lookup' values for faster aquisition
    var keyd = key;
    var val = arr[keyd];
    var nVal = arr[keyd - 1];
    var pVal = arr[++keyd];

   if ((val == "\"" || val == "'") && nVal != "\\") {
    if (quote == false) {
     quote = true;
     outhtml += val;
    }
    else {
     outhtml += val;
     quote = false;
    }
    locator[locatorIndex++] = parseInt(key);
   }
   else if (numerals.test(val) && quote == false && blockComment == false && regex == false) {
    outhtml += '<span class="num">' + val + '</span>';
   }
   else if (val == "/" && nVal != "<") {
    var keys = key;
    if (pVal == "/") {
     comment = true;
     continuation = key;
     break;
    }
    else if (pVal == "*") {
     outhtml += "/";
     blockComment = true;
     locator[locatorIndex++] = parseInt(key);
    }
    else if (nVal == "*") {
     outhtml += "/";
     blockComment = false;
     locator[locatorIndex++] = parseInt(key);
    }
    else if (pVal == "[" && regex == false) {
     outhtml += "<span class='res'>/";
     regex = true;
    }
    else {
     outhtml += "/";
    }
   }
   else if (val == "," || val == ";" && regex == true) {
    outhtml += "</span>" + val;
    regex = false;
   }
   else {
    outhtml += val;
   }
  }

  if (comment == true) {
   outhtml = outhtml.replace(keywords, "<span class='res'>$1</span>");
   outhtml += '<span class="com">';
   outhtml += text.substring(continuation, text.length);
   outhtml += '</span>';
  }
  else {
   if ((locator.length % 2) != 0) locator[locator.length] = (text.length - 1);

   if (locator.length != 0) {
    text = outhtml;

    outhtml  = text.substring(0, locator[0]).replace(keywords, "<span class=\"res\">$1</span>");

    for (var i = 0; i < locator.length;) {
     qTest = text.substring(locator[i], locator[i] + 1);
     if (qTest == "'" || qTest == "\"") outhtml += "<span class=\"quo\">";
     else outhtml += "<span class=\"com\">";

     outhtml += text.substring(locator[i], locator[++i] + 1) + "</span>";

     outhtml += text.substring(locator[i] + 1, locator[++i]).replace(keywords, "<span class=\"res\">$1</span>");
    }
   }
   else {
    outhtml = outhtml.replace(keywords, "<span class=\"res\">$1</span>");
   }
  }

  text = outhtml;
  $(this).html(text);
  return blockComment;
 }
})(jQuery);

我并不是说这是最有效的方法,也不是最好的方法,但它确实有效。可能还有几个bug我还没有识别出来(我知道有一个bug,但我还没有开始修复),但是如果你愿意的话,这应该能让你知道你该怎么做。

我建议的实现方法是创建一个textarea或其他东西,并在单击按钮或其他东西时运行插件(就测试它而言,这是一个不错的想法),当然,您可以将文本区域中的文本设置为一些启动代码,以确保其工作正常(提示:您可以在<textarea>标记之间放置标记,它将呈现为文本,而不是HTML)。

另外,blockComment是一个布尔值,请确保传递false,因为true将触发块引用。如果您决定逐行解析某些内容,例如:

代码语言:javascript
复制
<a>code</a>
<a>some more code</a>

做以下事情:

代码语言:javascript
复制
blockComment = false;
$("a").each(function() {
  blockComment = $(this).codeBlock(blockComment);
});
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4250899

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档