JavaScript的语法高亮一直是个难点,因为需要语义分析以确定/是除法操作的开始还是正则表达式的开始。目前关于高亮js的语法高亮都不是很理想,尤其是syntaxhighlighter(你待会看到的代码高亮效果就是它弄的, csdn说, 就用sh了)的效果算是最差的了,根本就不高亮正则、数字等,太不敬业了。假设你写的代码是足够规范的,而且不考虑效率的话,那么你使用我这个高亮js一般不会有问题。

语法高亮最初我是想做但感觉很难,但前阵子偶然看到一个很牛的女程序员Ider(博客地址Ider),绝对很牛,写了一个C++的语法高亮Regular Expression for C++ Code Syntax Coloring (Version 1.0),我按耐不住了,决心也要写一个。

关于更多的高亮javascript的,请访问Ben Joffe(悉尼的绝绝对对大牛)的JavaScript Syntax Highlighter,这个估计是目前最好的高亮js的,当然最好的高亮js的应该属aptana和netbeans了(但它们都不适用于网页)

以下是一个Hack SH的js高亮示例:

var re = /'abc/g, str = 'str'; // I can't imagine this will DO highlight well

效果图:

js的

C++的

以下是源码(前面说过SH高亮很烂,所以这儿没用高亮,把下面的源码复制到文本编辑器中然后保存为utf8编码的html后用浏览器(推荐opera或chrome浏览器)可以打开测试了,当然不用utf8也不要紧,我没有使用utf8字符,呵呵),你需要一定的正则表达式基础来读懂以下源码,希望哪天我能有时间解释下。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Highlight Code Version 2.0(2011-10-20)</title>
    <style type="text/css">
      * { padding: 0; margin: 0; }
      #main { width: 800px; margin: auto; }
      #code { font-size: 0.8em; padding: 0.2em 0; }
      #codesettings { border: 1px dotted #888; margin: 0.4em 0; padding: 0.1em 0; }
      #codesettings label { display: block; text-indent: 0.2em; }
      #codesettings input { width: 2em; }
      #settingstitle { font-size: 1.1em; font-weight: bold; }
      #code textarea { width: 100%; height: 200px; }
      #presentation { line-height: 1.2em; font-size: 0.8em; font-family:monospace; width: 800px; } /* fix IE6, making lineno and code of the same height */
      #lineno { float: left; width: 60px; text-align: right; color: #990033; background-color: #cccccc; }
      #highlightcode { float: left; width: 734px; margin-left: 6px; white-space: nowrap; overflow-x: auto; }

/* custom code style class defined here */
      /* add each language style className with the RELATED option value as prefix in [Select a Programing Language] select list */

/* for C/C++ */
      .cppstring { color:#ff0000; }
      .cppcomment { color:#008800; }
      .cppcharacter { color:#ff00cc; }
      .cpppreprocessor { color:#006666; }
      .cppidentifier { color:#0000ff; }
      .cppkeyword { color:#ff3300; font-weight:bold; }
      .cppnumber { color:#990099; }
      .cppoperator { color:#000066; }
      .cppuserhighlight { color:#0099ff; }

/* for JavaScript */
      .jsstring_dq { color:#ff0000; }
      .jscomment { color:#008800; }
      .jsstring_sq { color:#ff00cc; }
      .jsidentifier { color:#0000ff; }
      .jskeyword { color:#ff3300; font-weight:bold; }
      .jsnumber { color:#990099; }
      .jsoperator { color:#000066; }
      .jsuserhighlight { color:#0099ff; }
      .jsregexp { color: #fe5677; }
      .jsloprand { color: #000000; }

/* TODO: other language css style adds here */
    </style>
  </head>
  <body>
    <div id="main">
      <br />
      <div style="font-size:0.9em;"><strong><em>A simple highlight (JavaScript/C/C++) code parser based on regular expression, works fine with IE6 and the latest FF/Chrome/Opera(<span style="color:green; font-size:0.9em;">have a small align bug in Safari between lineno and highlight code</span>), hope you can enjoy, designed by Wind Fantasy &copy; 2011-10-20</em></strong></div>
      <div style="overflow-x: hidden;"> ----------------------------------------------------------------------------------------------------------------------------- </div>
      <div style="color: #008800; font-size: 0.8em;">Version 2.0: Now I have partly fixed the <em>JavaScript Highlight bug</em> by supposing that '/' stands for division only if '/' follows <strong style="color: #ff0000;">({number}|{identifier}|[\)\]}])[ \t]*</strong> directly, as we know that '/' needs a left operand for division</div>
      <div style="font-size: 0.8em;">Please visit <a href="http://www.benjoffe.com/code/projects/syntax/" target="_blank">JavaScript Syntax Highlighter</a> for more information about JavaScript Highlight.</div>
      <br />
      <div id="code">
        <div id="action">
          <button id="hidecodesettings" type="button">Hide Code Settings</button>
          &nbsp;<button id="highlight" type="button">Highlight Textarea Code</button>
          &nbsp;<button id="testjsself" type="button">Highlight JavaScript Of Current Document</button>
        </div>
        <form autocomplete="off">
          <div id="codesettings">
            <div id="settingstitle">Code Settings</div>
            <label>Select a Programing Language:
              <select id="language">
                <option value="cpp">C/C++</option>
                <option value="js">JavaScript</option>
              </select>
            </label>
            <label>Select Formatting Method:
              <select id="formattingmethod">
                <option value="pre">Use Pre Tag (Fast)</option>
                <option value="entity">Use HTML Entity (Slow)</option>
              </select>
            </label>
            <label><em>(Depreciated)</em> Highlight With Line Number:
              <input type="checkbox" checked="checked" id="withlineno" disabled="disabled" />
            </label>
            <label><em>(Depreciated)</em> Tab Width(works only when <strong>[Select Formatting Method] &gt; Use HTML Entity</strong> is Selected):
              <input type="text" id="tabwidth" value="4" maxlength="1" />
            </label>
            <!--
            <label>Line Number Min Width(works only when <strong>[Highlight With Line Number]</strong> is Checked):
              <input type="text" id="linenominwidth" value="4" />
            </label>
            -->
            <label>
              <button id="submitcodesettings" type="button">Save Code Settings &amp; Restart to Hightlight</button>
            </label>
          </div>
          <div style="padding: 3px;">Time used: <span id="time" style="color: #FF0000;">0.000</span> s <span style="color: #008800;">(I think the latest opera browser is the fastest)</span></div>
          <div id="codetext">
            <textarea id="sourcecode">
// input some codes here to test, please help yourself
#include<cstdio> // work as well
#include <iostream>
#include <string>
using namespace std;

/*
  swap int x and int y quickly with ^
  we expect x, y is an int variable, must NOT be (const) expression
  such as swap(1,y) OR swap(a+b, c), the same as swap_slow
*/
#define swap(x,y) \
x ^= y; \
y ^= x; \
x ^= y;

/*
  swap int x and int slowly with temp
*/
#define swap_slow(x,y) \
int temp = x; \
y = x; \
x = temp;

int main() {

string s = "uvwxyz"; // nomal C++ string
 
  /**
    line-continuing string
  */
  char[] lcs = "ABC\x44D\
EF\
G\
";

/**
    special line-continuing string
  */
  char[] slcs = "abc\\\"\\\
continue\
end";

/**
    invalid line-continuing string 1
    no line-continuing character (pattern) /\\(?:\r?\n)/ to be found
  */
  char[] ilcs1 = "abc\\\"\\
invalidremain\
invalidend";

/**
    invalid line-continuing string 2
  */
  char[] ilcs2 = "abc\"\
def\
badend // no quote enclosed to be found

char c = '\x41'; // character 'A'
 
  // line-continuing character
  char lcc = '\
  \
  \x\
  42'; // character 'B'
 
  // no enclose double quote " string
  char* partly_s = "abcdefg
  // no enclose single quote ' character
  char partly_c = 'z
 
  float f = 1.2f;
  double d = 3.// 3.0
  double d2 = .3// 0.3
  double e = .1234e-3L; // long double
  unsigned int ui = 5678u;
  long int li = 9l; // not 91
  int i = 100;
  double cast = 12345678f; // int to float, float to double
  long int lhex = 0x12aBL;
  unsigned int uhex = 0XFf23u;
  int hex = 0xcD89;
  int invalid = 0xZ123; // invalid hex number

cout << s << endl;

return 0;
}
            </textarea>
          </div>
        </form>
      </div>
      <div id="presentation">
        <div id="lineno"></div>
        <div id="highlightcode"></div>
      </div>
    </div>
    <script id="jsself" type="text/javascript">
      // new bugs: (These are even difficult to be fixed because we need further analysising.)
      var hacknum = 0;
      {} /re/.test('re'); // {} becomes an empty statement so that /re/ should be highlighted as a R.E.
      hacknum++ / 1 / 2; // division not R.E
      /[/]/.test('/'); // non-escaped '/' in a character set of R.E. is interpreted as the end of R.E. unfortunately
      hacknum = 1
      / // single-line comment does NOT work
      0.5
     / 2; // the first '/' is NOT a delimiter of R.E. as you know that hacknum is 1 later;
      var hacknull = null / 2; // division not R.E.
      
      // !spam, partly fixed Version 1.0. Oh, JavaScript is NOT that easy!
      // the big problem in Highlight JavaScript Code:
      // code below is test for hacking, division symbol '/' is treated as a delimiter of the beginning of regular expression
      // so far I have NOT (found) any way based on regular expression determining whether '/' stands for division(operator) or not(that is, for delimiter)
      // sometimes we need Syntax Analysis, or even Semantic Analysis
      // be careful with the code (being or like) below, which will cause confusing representation of the code according to its real meaning
      // if we don't analysis R.E.(short for regular expression), quote(s) in R.E. will cause error when try to highlight/analysis quoted string
      // else(that is we analysis R.E.) we don't know whether '/' stands for division(operator) or not
      // [1]. I have NOT fixed part R.E.(fixed string as you can test, that is, a string defined like 'var s="abc', no enclose ", will be highlighted as string)
      // [2]. I always suppose that your js code is clean and well-orgnized and you hardly use '/' as division twice or more OR mixed R.E. and division in the same line
      // [3]. I always suppose your js code to be block not inline, you know(that is, multiline, so that an error ruins at most ONE line)
      // [4]. The most important is that I suppose you DO according to the three rules above
      var hacknum = 1/2, hackre = /"test/, hackcomment = "abc"; // this SHOULD have been single-line comment, but it is NOT as you see
      // spam!
      
      var HighlightParser =(function () {
        // if you want to use jQuery $, please define a variable alias of $ by assignment, for example: var alias_$ = $, OR use jQuery itself
        var $ = { // create a container so that we can access the previous attributes or methods next step by $.attributename or $.methodname
          'library': {
            // PHP-Partly-Compatible htmlspecialchars and htmlspecialchars_decode
            'htmlspecialchars': function (str, encode_sq) { // make html special chars their entities, bool encode_sq means whether we wanna convert single quote to its entity
              var ent = { '>': '&gt;', '<': '&lt;', '&': '&amp;', '"': '&quot;' };
              ent["'"] = encode_sq ? ''' : "'";
              return str.replace(/[\<\>&"']/g, function () { return ent[arguments[0]]; } );
            },
            'htmlspecialchars_decode': function (str, decode_sq) { // decode of htmlspecialchars
              var ent_r = { '&gt;': '>', '&lt;': '<', '&amp;': '&', '&quot;': '"'};
              ent_r['''] = decode_sq ? "'" : ''';
              return str.replace(/&(?:gt|lt|quot|#039|amp);/g, function () { return ent_r[arguments[0]]; });
            },
            /*
            'htmlspace': function (str) {
              var ent = { '\n': '<br \/>', '\r\n': '<br \/>', '\t': $.config.tabreplacement };
              //alert('sp:' + str + '*')
              return str.replace(/\r?\n|\t|(\s)/g, function () { var $ = arguments; /*alert('1' + $[1] + '1'); if(! prompt('', false)) throw 'hi';* / return $[1] ? '&nbsp;' : ent[$[0]]; });
            },
             */
            'htmlspace': function (str) { // make html spaces(\t \n) its real representation in text mode
              var ent = { '\t': $.config.tabreplacement, ' ': '&nbsp;'}
              return str.replace(/[\t ]/g, function () { return ent[arguments[0]]; });
            },
            'htmlbreakline': function (str, tagname) { // make html break-line character its real representation in text mode
              if (! tagname) { // tagname means using tagname instead of tag br to render representation, possiablely use div, but div is block default while span is inline(this will cause problem)
                return str.replace(/\r?\n/g, '<br \/>\r\n');
              }
              var bothtag = [ ['<', '>'].join(tagname), ['</', '>'].join(tagname)];
              // return str.replace(/^.*$/mg, function () { return bothtag.join(arguments[0]); });
              return str.replace(/(?:^|\r?\n)([^\r\n]*)/g, function () {
                var $1 = String(arguments[1]);
                //alert($1 + '*' + $1.charCodeAt(0) + '.' + $1.charCodeAt(1));
                //alert(bothtag.join(arguments[1] || 'nbsp;'))
                return bothtag.join(arguments[1] || '&nbsp;'); });
            },
            'htmlpre': function (str, encode_sq) { // make representation of str in html mode the same as pre mode
              //alert('pre:' + str + '*')
              return $.library.htmlspace( $.library.htmlspecialchars(str, encode_sq) );
            },
            'objecttoarray': function (obj, includeprototype) { // reuturn an array of each propery VALUE of obj
              var a = [];
              for (var prop in obj) {
                if (includeprototype || obj.hasOwnProperty(prop))
                  a.push(obj[prop]);
              }
              return a;
            },
            'propertytoarray': function (obj, includeprototype) { // return an array of each propery NAME of obj
              var a = [];
              for (var prop in obj) {
                if (includeprototype || obj.hasOwnProperty(prop))
                  a.push(prop);
              }
              return a;
            },
            'repeat': function (repeat, times) { // return a string when variable "repeat" repeats "times" times
              return new Array(times + 1).join(repeat);
            }
          },
          'config': {
            'language': 'js', // [current/selected] programing language in ['cpp', 'js', ... etc.]
            'formattingmethod': 0 ? 'pre' : 'entity', // formatingmethod in ['pre', 'entity'] for [pre tag method(Fast), HTML entity method(Slow)]
            'withlineno': false, // highlight with line number
            'tabwidth': 4, // works only when formattingmethod is 'entity'
            //'linenominwidth': 4, // works only when withlineno is true
            'tabreplacement': new Array(4 + 1).join('&nbsp;'), // but $.library.repeat('&nbsp;', $.config.tabwidth) doesn't work // replacement for tab
            'updateTabwidth': function (tabwidth) {
              $.config.tabwidth = tabwidth;
              $.config.tabreplacement = new Array(tabwidth + 1).join('&nbsp;');
            }
          },
          'regexp': { // core regular expressions for parser
            'cpp': {
              // both of 'string'(comment and uncomment) regexp below take the same effect
              //'string': '"(?:\\\\(?:\\\\|"|\\r?\\n)|[^"\\n])*"?', // first is ", /"(?:\\(?:\\|"|\r?\n)|[^"\n])*"?/
              'string': '"(?:\\\\(?:\\r?\\n|.)|[^"\\n\\\\])*"?', // first is ", /"(?:\\(?:.|\r?\n)|[^"\n\\])*"?/
              'character': "'(?:\\\\(?:\\\\|'|\\r?\\n)|[^'\\n])*'?", // first is ', /'(?:\\(?:\\|'|\r?\n)|[^\n])*'?/
              'preprocessor': '(?:^|\\r?\\n)[^\\S\\n]*#[^\\S\\n]*[a-zA-Z]+', // first is #, /(?:^|\r?\n)[^\S\n]*#[^\S\n]*[a-zA-Z]+/
              'keyword': '(?:asm|auto|bad_cast|bad_typeid|bool|break|case|catch|char|class|const|const_cast|continue|default|delete|do|double|dynamic_cast|else|enum|except|explicit|extern|false|finally|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_cast|struct|switch|template|this|throw|true|try|type_info|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)(?=\\W|$)',
              'userhighlight': '(?:assert|cout|cin|endl|std|string)(?=\\W|$)',
              'identifier': '[^\\W\\d]\\w*', // first is [^\W\d], /[^\W\d]\w*/
              //'number': '(?:0[xX][\\da-fA-F]+|\\d+)(?:[Ll]?[Uu]?|[Uu]?[Ll]?)|(?:\\d+\\.?\\d*|\\d*\\.?\\d+)(?:[Ee][+-]?\\d+)?[LlFf]?', // first is [\d\.], /(?:0[xX][\da-fA-F]+|\d+)(?:[Ll]?[Uu]?|[Uu]?[Ll]?)|(?:\d+\.?\d*|\d*\.?\d+)(?:[Ee][+-]?\d+)?[LlFf]?/
              'number': '0[xX][\\da-fA-F]+(?:[Ll]?[Uu]?|[Uu]?[Ll]?)|\\d+(?:[Ll][Uu]?|[Uu][Ll]?)|(?:\\d+\\.?\\d*|\\d*\\.?\\d+)(?:[Ee][+-]?\\d+)?[LlFf]?', // first is [\d\.], /0[xX][\da-fA-F]+(?:[Ll]?[Uu]?|[Uu]?[Ll]?)|\d+(?:[Ll][Uu]?|[Uu][Ll]?)|(?:\d+\.?\d*|\d*\.?\d+)(?:[Ee][+-]?\d+)?[LlFf]?/
              //'comment': '//.*|/\\*(?:[^*]|\\*[^\\/])*(?:\\*/)?', // first is /, expect * or / to be followed, /\/\/.*|\/\*(?:[^*]|\*[^\/])*(?:*/)?/
              'comment': '//.*|/\\*(?:[^*]|\\*(?!\\/))*(?:\\*/)?', // first is /, expect * or / to be followed, /\/\/.*|\/\*(?:[^*]|\*(?!\/))*(?:\*\/)?/
              'operator': '(?:[-!+*/%&^|=><]|>>|<<)=?|[?:]', // /(?:[-!+*/%&^|=><]|>>|<<)=?|[?:]/
              'space': '[^\\S\\n]+' // first is [^\\S\\n], /[^\\S\\n]+/
            },
            'js': {
              'string_dq': '"(?:\\\\(?:\\\\|"|\\r?\\n)|[^"\\n])*"?', // first is ", /"(?:\\(?:\\|"|\r?\n)|[^"\n])*"?/, $1
              'string_sq': "'(?:\\\\(?:\\\\|'|\\r?\\n)|[^'\\n])*'?", // first is ', /'(?:\\(?:\\|'|\r?\n)|[^\n])*'?/, $2
              'keyword': '(?:abstract|boolean|byte|char|class|const|debugger|double|enum|export|extends|final|float|goto|implements|import|int|interface|long|native|package|private|protected|public|short|static|super|synchronized|throws|transient|volatile|break|case|continue|default|do|else|false|function|if|in|instanceof|null|new|return|switch|this|true|typeof|undefined|var|void|while)(?=\\W|$)',
              'userhighlight': '(?:Array|Bool|Date|Function|Global|Math|NaN|Number|Object|RegExp|String|apply|call|constructor|document|window)(?=\\W|$)',
              'identifier': '[$_a-zA-Z][\\w\\$]*', // first is [$_a-zA-Z], /[$_a-zA-Z][\w\$]*/, $5
              'number': '0[xX][\\da-fA-F]+|(?:\\d+\\.?\\d*|\\d*\\.?\\d+)(?:[Ee][+-]?\\d+)?', // first is [\d.], /0[xX][\da-fA-F]+|(?:\d+\.?\d*|\d*\.?\d+)(?:[Ee][+-]?\d+)?/, $6
              //'comment': '//.*|/\\*(?:[^*]|\\*[^\\/])*(?:\\*/)?', // first is /, expect * or / to be followed, /\/\/.*|\/\*(?:[^*]|\*[^\/])*(?:*/)?/
              'comment': '//.*|/\\*(?:[^*]|\\*(?!\\/))*(?:\\*/)?', // first is /, expect * or / to be followed, /\/\/.*|\/\*(?:[^*]|\*(?!\/))*(?:\*\/)?/
              //'loprand': '\\)\\s*/(?![*/])', // first is ), /\)\s*\/(?![*\/])/
              'loprand': '(?:[\\])]\\s*|\\}[ \\t]*)/(?![*/])', // first is )]}, /(?:[\])]\s*|\}[ \t]*)\/(?![*\/])/
              //'regexp': '/(?:\\\\/|[^/\\n])*/?[gmi]*', // first is /, /\/(?:[^\/\n]|\\\/)+)\//[gmi]*
              //'regexp': '/(?:\\\\[/\\\\]|[^/\\n])+/[gmi]*[^\\S\\n]*', // first is /, /\/(?:\\[\/\\]|[^\/\n])+\/[gmi]*[^\S\n]*(?![\w])/
              //'regexp': '/(?:\\\\[\\/\\\\]|[^/\\n\\\\])+/[gmi]*', // first is /, /\/(?:\\[\/\\]|[^/\n\\])+\/[gmi]*/
              'regexp': '/(?:\\\\.|[^\\\\\\n/])+/[gmi]*', // first is /, /\/(?:\\.|[^\\\n\/])+\/[gmi]*/, $9
              'operator': '(?:[-!+*/%&^|=><]|>>|<<)=?|=|[?:]', // /(?:[-!+*/%&^|=><]|>>|<<)=?|[?:]/
              'space': '\\s+' // first is \s, /\s+/
            },
            'html': { // to be implemented
              'tag': '<([a-zA-Z])(\\s>)*>.' // /<([a-zA-Z]+)((?:\s+[-\w]+=(?:'[^']*'|"[^"]*"))*)\s*>(.*)(?:<\/\1>)?/
            }
          },
          'getCompiledPattern': function(language) {
            var pattern = '(' + $.library.objecttoarray($.regexp[language]).join(')|(') + ')';
            return new RegExp(pattern, "g");
          },
          'getCurrentPattern': function () {
            return $.getCompiledPattern($.config.language);
          },
          'parse': function (sourcecode) {
            // first we convert windows break line "\r\n" to unix/linux "\n" to fix opera/safari bug
            sourcecode = sourcecode.replace(/\r(?=\n)/g, ''); // fix opera/safari(Opera/Safari will treat '\r' as the same representation of '\n')
            var language = $.config.language, classNames = $.library.propertytoarray($.regexp[language]);
            var premethod = ($.config.formattingmethod == 'pre');
            var htmlformater = premethod ? $.library.htmlspecialchars
                                : function (str, encode_sq) { return $.library.htmlspace($.library.htmlspecialchars(str, encode_sq));};

if (language == 'js') {
              var pattern = new RegExp( '(' + $.library.objecttoarray($.regexp[language]).join(')|(') + ')' );
              var isdivision = false, s = [], turnback;
              var divisionflag = [null, true, true, false, false, true, true]; // only 1, 2, 5, 6 subpattern can be placed before division
              var next = sourcecode, matches, i, len, highlightcode, htmlspace = function (str) { return premethod ? str : $.library.htmlspace(str); };
              
              while ( (matches = pattern.exec(next)) != null) {
                for (i = 1, len = matches.length; i < len; ++i) {
                  if (matches[i]) {
                    if (i == 9 && isdivision && matches.index == 0) { // when try to match regexp, but '/' turns out to be division, sorry we should turn back
                      s.push([htmlformater(next.substr(0, matches.index), true), '<span class="jsoperator"\>/\<\/sapn\>'].join(''));
                      turnback = true;
                      next = next.substr(matches.index + 1);
                    } else if (i == len - 1) { // spaces?
                      s.push ( htmlformater(next.substr(0, matches.index + matches[i].length), true) );
                    } else if (i == 8) { // loperand before '/'? i.e. '(function () { return 1; })()  / 2', matches[0] is ')  /'
                      s.push ( [htmlformater(next.substr(0, matches.index), true), '<span class="js', classNames[i-1], '"\>', htmlspace(matches[i]).replace('/', '\<span class="jsoperator"\>/\<\/sapn\>'), '\<\/span\>'].join('') );
                    } else {
                      s.push ( [htmlformater(next.substr(0, matches.index), true), '<span class="js', classNames[i-1], '"\>', htmlformater(matches[i], true), '\<\/span\>'].join('') );
                    }
                    if (i == len - 1) {
                      isdivision = (matches.index == 0 && matches[0].indexOf('\n') == -1) ? isdivision : false;
                    } else {
                      isdivision = Boolean(divisionflag[i]);
                    }
                    break;
                  }
                }
                if (! turnback) {
                  next = next.substr(matches.index + matches[0].length);
                } else {
                  turnback = false;
                }
              }
              s.push(next);
              highlightcode = s.join('');
            } else {
              var replace_callback = function () {
                var matches = arguments;
                var reallen = matches.length - 3; // strip last spaces, position where pattern starts to match and the original string to be replaced
                for (var i=1; i < reallen; ++i) {
                  if(matches[i]) {
                     //alert(['*', matches[i], '*', matches[i].length, '*'].join(''));
                    return ['<span class="', language, classNames[i-1], '">', htmlformater(matches[i], true), '<\/span\>'].join('');
                    break;
                  }
                }
                return htmlformater(matches[0], true);
              }
              highlightcode = sourcecode.replace($.getCurrentPattern(), replace_callback);
            }
            return premethod ? ['<pre>\r\n', '</pre>'].join(highlightcode) : $.library.htmlbreakline(highlightcode, false);
          },
          'getLineNoHTML': function (sourcecode) {
            var linecount = sourcecode.split('\n').length, w = String(linecount).length;
            var repeat = $.library.repeat, s, a = [];
            for (var i=1; i <= linecount; ++i) {
              s = String(i);
              a.push( [repeat('0', w - s.length), s, '&nbsp;'].join('') ); // possiblely use &nbsp; instead of 0
            }
            if($.config.formattingmethod == 'pre') {
              return ['<pre\>', a.join("\r\n"), '\r\n<\/pre>'].join('');
            }
            return a.join("\r\n<br \/>");
          }
        };
        return $;
      })();
      function g(id) {
        return document.getElementById(id);
      }
      window.onload = function () {
        var elineno = g('lineno');
        var ehighlightcode = g('highlightcode');
        var esourcecode = g('sourcecode');
        var elanguage = g('language');
        var ewithlineno = g('withlineno');
        var etabwidth = g('tabwidth');
        var ecodesettings = g('codesettings');
        var eformattingmethod = g('formattingmethod');
        var time = g('time');
        var cfg = HighlightParser.config;
        
        g('hidecodesettings').onclick = function () {
          var style = ecodesettings.style;
          if (style.display == 'none') {
            style.display = 'block';
            this.innerHTML = 'Hide Code Settings';
          } else {
            style.display = 'none';
            this.innerHTML = "Display Code Settings";
          }
        }
        var highlight = function () {
          var t = new Date().getTime();
          elineno.innerHTML = HighlightParser.getLineNoHTML(esourcecode.value);
          
          ehighlightcode.innerHTML = HighlightParser.parse(esourcecode.value);
          time.innerHTML = String( (new Date().getTime() - t) / 1000 );
          if (window.ActiveXObject) { // fix ie6
            ehighlightcode.style.height = elineno.clientHeight + 20 + 'px';
          }
        }
        var reloadconfig = function () {
          cfg.language = elanguage.value;
          cfg.withlineno = ewithlineno.checked;
          cfg.formattingmethod = eformattingmethod.value;
          cfg.updateTabwidth(parseInt(etabwidth.value, 10));
        }
        g('submitcodesettings').onclick = function () {
          reloadconfig();
          highlight();
        }
        g('highlight').onclick = function () {
          highlight();
        }
        g('testjsself').onclick = function () {
          esourcecode.value = g('jsself').innerHTML;
          /* There is a small difference(innerHTML of html script node) between w3c-compatible browser and IE6, here you can test
          var v = esourcecode.value, a = [0, 1, 2, 3], s = [];
          for (var i in a) {
            s.push(v.charCodeAt(a[i]));
          }
          alert(s);
          */
          elanguage.selectedIndex = 1;
          reloadconfig();
          highlight();
        }
        reloadconfig();
        highlight();
      }
    </script>
  </body>

</html>

基于正则表达式的JavaScript/C++语法高亮(js版)相关推荐

  1. js中怎么使用php代码高亮,PHP_如何实现正则表达式的JavaScript的代码高亮,今天想改一下JS的高亮的配色 - phpStudy...

    如何实现正则表达式的JavaScript的代码高亮 今天想改一下JS的高亮的配色,憋了一下午憋出了这个这个正则表达式. 下面这老长老长了的玩意儿是个正则表达式,看到了别吓坏了. /(\/\/.*|\/ ...

  2. JavaScript基本语法:JS运算符

    在写这篇博客之前,写给出下面几个问题,请你们小试牛刀一下 ** var a=10; var b1=a++; var b2=++a; var b3=a+++++a+a++; var b4=1+2+&qu ...

  3. highlight.js 语法高亮,让你的页面更美观~

    在网页开发过程中,经常会用到代码的展示,而不同颜色的代码,可以让页面看起来更直观,也更美观. highlight.js是一款基于JavaScript的语法高亮库,目前支持125种编程语言,有63种可供 ...

  4. js 正则练习之语法高亮

    js 正则练习之语法高亮 原文:js 正则练习之语法高亮 学了几天正则,差不多该总结整理写成果了,之前就想写语法高亮匹配来着,不过水平不够,看着例子都不理解. 今天就分析下 次碳酸钴 和 Barret ...

  5. WebStorm 自定义字体+颜色+语法高亮+导入导出用户设置

    WebStorm 自定义字体+颜色+语法高亮+导入导出用户设置 WebStorm是一个捷克公司开发的,功能虽然很强大,但UI貌似一直不是东欧人的强项.WebStorm默认的编辑器颜色搭配不算讲究,我看 ...

  6. C# 代码编辑器实现篇-语法高亮

    创建 C# 编辑器 实现效果 实现步骤 本片介绍基于 AvalonEdit 实现一个支持语法高亮的 C# 编辑器 实现效果 语法高亮 点击编译 实现步骤 在VS中创建窗体应用程序.通过 Nuget 引 ...

  7. 小汤学编程之JavaScript学习day01——认识JS、JS基础语法

    一.认识JS 1.JavaScript的组成     2.浏览器执行js简介     3.JavaScript是什么?     4.扩展内容 二.JS基础语法 1.代码书写位置     2.变量    ...

  8. 想有自己的博客吗?浏览器支持 MarkDown和语法高亮的最简单示例(使用markdown-it、highlight.js和mermaid)

    MarkDown,写作神器,还是有必要掌握一下.写作也是一种很重要的能力,需要长久坚持和锻炼. 写作能力重不重要?语文重不重要?读书重不重要? 我觉得语文和写作能力是所有能力的基础,是重中之重.因为你 ...

  9. html js 正则表达式语法大全,js正则表达式语法大全(JS regular expression syntax Daquan).doc...

    js正则表达式语法大全(JS regular expression syntax Daquan) js正则表达式语法大全(JS regular expression syntax Daquan) re ...

最新文章

  1. 企业号、订阅号、服务号的一此区别
  2. zabbix企业应用之固定端口监控redis
  3. 使用单个innodb表,实现锁,防止游戏被刷物品或者其它资源!
  4. 洛谷P1085不高兴的津津
  5. CDH、CM下载403,Cloudera收费无法下载解决,CDH安装包下载
  6. 2020年编程现状:Python将成为第一大编程语言,中国开源涨势最猛
  7. hdoj 4790 Just Random 【数学】
  8. strong,weak, retain, assign的区别@property的参数
  9. 频谱感知3:合作频谱检测中的硬合并与软合并
  10. dll反编译工具ILspy下载及使用
  11. 详细的vsftpd配置文件讲解
  12. 最近刷爆微信抖音的夏日便捷小空调小程序源码
  13. htm html mht 无图标,mht文件与html文件有何区别?
  14. weblogic启动慢原因
  15. 喜欢这样的游戏---流畅的俯视坦克射击游戏
  16. 什么是线性电路,非线性电路
  17. 普罗米修斯 mysql监控_Promethus(普罗米修斯)监控Mysql数据库
  18. SpringBoot 整合 Elasticsearch
  19. 网易易盾-滑块-cb参数
  20. JETSON NANO清除磁盘(SD卡无法被电脑识别)

热门文章

  1. 计算机关机慢怎么解决方法,电脑关机很慢,详细教您win7电脑关机很慢的解决方法...
  2. EduCoder-Web程序设计基础 -web编程训练-html5-文档头部-第1关:页面标题及字符集的设置
  3. 【TL第二期】动手学数据分析-第二章 数据预处理
  4. 数字人民币专利数激增, “区块链”领域大有可为
  5. 大数据学习——hive阶段:启动HiveServer2启动报TezConfiguration类NoClassDefFoundError错误
  6. android让字体左右对齐,Android 模仿微信读书文字左右对齐效果
  7. Sklearn官方文档中文整理4——随机梯度下降和最近邻篇
  8. ubuntu16.04编译obmc
  9. 【经验总结】keil报错:declaration may not appear after executable statement in block···
  10. 妈妈的手除了像写字板还像什么呢?