关于javascript:Javascript-实现对-C-的语法高亮

2次阅读

共计 23478 个字符,预计需要花费 59 分钟才能阅读完成。

这篇文章原本会比拟长,因为波及到许多种不同的高亮语言,但我在保障程序结构完整性的状况下依照不同的语言进行了拆分,也就是说这里的代码尽管不齐全,但也可能运行。这是用 Javascript 实现的语法高亮插件,当初反对的高亮语言有 C#、Javascript、HTML、CSS、Sql 这几种(这篇文章只包含高亮 C# 相干的代码,另有其它语言的高亮,参考我公布的相干文章),目前我本人罕用的语言是这几种,不过可能当前会更新其它语言。这个实现最后是我本人的集体网站所用的一个功能模块。之前我理解过其它我听过的语法高亮插件,比方闻名的 highlight.js,试用了一些,但始终没有找到能实现我现实中成果的那一个,而且它们大都是以 关键字高亮 为主。我这里指的是 语法高亮 可并不单纯的是简略的关键字高亮,在一部分网友眼里认为的语法高亮在我眼里其实只能叫做关键字高亮,比方 C# 中的 int x;DateTime time;,在我所理解的现有的语法高亮插件中,都只是对后面的 int 进行了着色,而前面的 DateTime 仍然不会变,然而在当初这个实现中 DateTime 能够也被扭转,当然还不只是这一点,其中也包含了泛型、动态援用和实例化等等语法的高亮。上面先贴出我的实现代码,前面再大抵介绍一下:

// 可用的语法着色数据
var Colors = {
    //C# 暗
    CSharpDark: {
        "language": "C#",
        "theme": "dark",
        "classColor": "#4EC9B0",
        "annotationColor": "#57A64A",
        "annotationsColor": "#57A64A",
        "stringColor": "#D69D85",
        "pragmaColor": "#9B9B9B",
        "keywordsInfo": [{
            "color": "#569CD6",
            "keywords": ["abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void", "volatile", "while", "add", "alias", "ascending", "async", "await", "by", "descending", "dynamic", "equals", "from", "get", "global", "group", "into", "join", "let", "nameof", "on", "orderby", "partial", "remove", "select", "set", "var", "when", "where", "yield"]
        }],
        "customClassInfo": [{
            "color": "#4EC9B0",
            "keywords": ["Assembly", "Console", "Convert", "Directory", "Encoder", "Encoding", "Graphics", "Guid", "HttpContext", "HttpUtility", "ImageFormat", "Image", "ImageCodecInfo", "MD5", "WebRequest"]
        }]
    }
};
// 应用某一种色彩数据对指定的文本进行语法着色(主入口)function StainColor(text, colorObj) {if (colorObj.language == "C#") {return StainGrammerCSharp(text, colorObj);
    }
}
//C# 语法着色
function StainGrammerCSharp(text, colorObj) {text = text.replace(/&/g, "&");
    text = text.replace(/\</g, "&lt;").replace(/\>/g, "&gt;");
    var t_regex = null;
    // 临时排除插值字符串
    var strings = new Array();
    var tstring = null;
    while (tstring = text.match(/\$"(?:(?:\\")|[^"\r\n])*"/)) {text = text.replace(/\$"(?:(?:\\")|[^"\r\n])*"/, "###str_{" + strings.length + "}###");
        strings.push(tstring[0]);
    }
    // 临时排除强制不本义字符串
    while (tstring = text.match(/@"(?:(?:"")|[^"\r\n])*"/)) {text = text.replace(/@"(?:(?:"")|[^"\r\n])*"/, "###str_{" + strings.length + "}###");
        strings.push(tstring[0]);
    }
    // 临时排除一般字符串
    while (tstring = text.match(/"(?:(?:\\")|[^"\r\n])*"/)) {text = text.replace(/"(?:(?:\\")|[^"\r\n])*"/, "###str_{" + strings.length + "}###");
        strings.push(tstring[0]);
    }
    // 临时排除多行正文
    var comments = new Array();
    var tcomment = null;
    while (tcomment = text.match(/\/\*(?:.|\s)*?\*\//)) {text = text.replace(/\/\*(?:.|\s)*?\*\//, "###comment_{" + comments.length + "}###");
        comments.push(tcomment[0]);
    }
    // 临时排除单行正文
    var annotations = new Array();
    var tannotation = null;
    while (tannotation = text.match(/\/\/.*/)) {text = text.replace(/\/\/.*/, "###annotation_{" + annotations.length + "}###");
        annotations.push(tannotation[0]);
    }
    // 临时排除预处理器指令
    var precompiles = new Array();
    var tprecompile = null;
    while (tprecompile = text.match(/# *if.*/)) {text = text.replace(/# *if.*/, "###precompile_{" + precompiles.length + "}###");
        precompiles.push(tprecompile[0]);
    }
    while (tprecompile = text.match(/# *else.*/)) {text = text.replace(/# *else.*/, "###precompile_{" + precompiles.length + "}###");
        precompiles.push(tprecompile[0]);
    }
    while (tprecompile = text.match(/# *elif.*/)) {text = text.replace(/# *elif.*/, "###precompile_{" + precompiles.length + "}###");
        precompiles.push(tprecompile[0]);
    }
    while (tprecompile = text.match(/# *endif.*/)) {text = text.replace(/# *endif.*/, "###precompile_{" + precompiles.length + "}###");
        precompiles.push(tprecompile[0]);
    }
    while (tprecompile = text.match(/# *define.*/)) {text = text.replace(/# *define.*/, "###precompile_{" + precompiles.length + "}###");
        precompiles.push(tprecompile[0]);
    }
    while (tprecompile = text.match(/# *undef.*/)) {text = text.replace(/# *undef.*/, "###precompile_{" + precompiles.length + "}###");
        precompiles.push(tprecompile[0]);
    }
    while (tprecompile = text.match(/# *error.*/)) {text = text.replace(/# *error.*/, "###precompile_{" + precompiles.length + "}###");
        precompiles.push(tprecompile[0]);
    }
    while (tprecompile = text.match(/# *line.*/)) {text = text.replace(/# *line.*/, "###precompile_{" + precompiles.length + "}###");
        precompiles.push(tprecompile[0]);
    }
    while (tprecompile = text.match(/# *region.*/)) {text = text.replace(/# *region.*/, "###precompile_{" + precompiles.length + "}###");
        precompiles.push(tprecompile[0]);
    }
    while (tprecompile = text.match(/# *endregion.*/)) {text = text.replace(/# *endregion.*/, "###precompile_{" + precompiles.length + "}###");
        precompiles.push(tprecompile[0]);
    }
    while (tprecompile = text.match(/# *pragma *warning *disable.*/)) {text = text.replace(/# *pragma *warning *disable.*/, "###precompile_{" + precompiles.length + "}###");
        precompiles.push(tprecompile[0]);
    }
    while (tprecompile = text.match(/# *pragma *warning *restore.*/)) {text = text.replace(/# *pragma *warning *restore.*/, "###precompile_{" + precompiles.length + "}###");
        precompiles.push(tprecompile[0]);
    }
    while (tprecompile = text.match(/# *warning.*/)) {text = text.replace(/# *warning.*/, "###precompile_{" + precompiles.length + "}###");
        precompiles.push(tprecompile[0]);
    }
    while (tprecompile = text.match(/# *pragma *checksum.*/)) {text = text.replace(/# *pragma *checksum.*/, "###precompile_{" + precompiles.length + "}###");
        precompiles.push(tprecompile[0]);
    }
    while (tprecompile = text.match(/# *pragma.*/)) {text = text.replace(/# *pragma.*/, "###precompile_{" + precompiles.length + "}###");
        precompiles.push(tprecompile[0]);
    }
    // 临时排除单字符
    var chars = new Array();
    var tchar = null;
    while (tchar = text.match(/(?:'\\?[^\\]')|''/)) {text = text.replace(/(?:'\\?[^\\]')|''/,"###char_{"+ chars.length +"}###");
        chars.push(tchar[0]);
    }
    // 临时排除类申明与定义局部
    var classes = new Array();
    var tclass = null;
    while (tclass = text.match(/class +@?\w+/)) {text = text.replace(/class +@?\w+/, "###class_{" + classes.length + "}###");
        classes.push(tclass[0]);
    }
    // 临时排除构造申明与定义局部
    var structs = new Array();
    var tstruct = null;
    while (tstruct = text.match(/struct +@?\w+/)) {text = text.replace(/struct +@?\w+/, "###struct_{" + structs.length + "}###");
        structs.push(tstruct[0]);
    }
    // 临时排除事件申明与定义局部
    var events = new Array();
    var tevent = null;
    while (tevent = text.match(/event +@?\w+/)) {text = text.replace(/event +@?\w+/, "###event_{" + events.length + "}###");
        events.push(tevent[0]);
    }
    // 临时排除接口申明与定义局部
    var interfaces = new Array();
    var tinterface = null;
    while (tinterface = text.match(/interface +@?\w+/)) {text = text.replace(/interface +@?\w+/, "###interface_{" + interfaces.length + "}###");
        interfaces.push(tinterface[0]);
    }
    // 临时排除异样捕捉的类型
    var exceptions = new Array();
    var texception = null;
    while (texception = text.match(/catch *\([ *@\w\.]+(?=(?: +@?\w+))/)) {text = text.replace(/catch *\([ *@\w\.]+(?=(?: +@?\w+))/, "###exception_{" + exceptions.length + "}###");
        exceptions.push(texception[0]);
    }
    // 临时排除 foreach 遍历的类型
    var foreachs = new Array();
    var tforeach = null;
    while (tforeach = text.match(/foreach *\([ *@\w\.]+(?= +@?\w+ +in)/)) {text = text.replace(/foreach *\([ *@\w\.]+(?= +@?\w+ +in)/, "###foreach_{" + foreachs.length + "}###");
        foreachs.push(tforeach[0]);
    }
    // 临时排除 is 表达式后的类型
    var ises = new Array();
    var tis = null;
    while (tis = text.match(/is +@?\w+[ *@\w\.]*/)) {text = text.replace(/is +@?\w+[ *@\w\.]*/, "###is_{" + ises.length + "}###");
        ises.push(tis[0]);
    }
    // 临时排除 as 表达式后的类型
    var ases = new Array();
    var tas = null;
    while (tas = text.match(/as +@?\w+[ *@\w\.]*/)) {text = text.replace(/as +@?\w+[ *@\w\.]*/, "###as_{" + ases.length + "}###");
        ases.push(tas[0]);
    }
    // 临时排除类型申明与初始化
    var types = new Array();
    var ttype = null;
    while (ttype = text.match(/@?\w+(?= *\?? *(?:\[\])? +@?\w+ *[;=,\)])/)) {text = text.replace(/@?\w+(?= *\?? *(?:\[\])? +@?\w+ *[;=,\)])/, "###type_{" + types.length + "}###");
        types.push(ttype[0]);
    }
    // 临时排除 new 关键字的类型实例化
    var newes = new Array();
    var tnew = null;
    while (tnew = text.match(/new +@?[\w\.@]+ *[\(\[]/)) {text = text.replace(/new +@?[\w\.@]+ *[\(\[]/, "###new_{" + newes.length + "}###");
        newes.push(tnew[0]);
    }
    // 临时排除泛型申明与一般办法的泛型返回类型
    var genericsl = new Array();
    var tgenericl = null;
    while (tgenericl = text.match(/@?\w+(?= *(?:&lt;) *@?\w+(?:(?:&lt;)|(?:&gt;)|,|@|\w| |\.)* *(?:&gt;)(?: *\[ *\])? +@?\w+ *[;=,\(\)])/)) {text = text.replace(/@?\w+(?= *(?:&lt;) *@?\w+(?:(?:&lt;)|(?:&gt;)|,|@|\w| |\.)* *(?:&gt;)(?: *\[ *\])? +@?\w+ *[;=,\(\)])/, "###genericl_{" + genericsl.length + "}###");
        genericsl.push(tgenericl[0]);
    }
    // 临时排除 new 关键字的泛型实例化
    var newgenerics = new Array();
    var tnewgeneric = null;
    while (tnewgeneric = text.match(/new +@?[\w@]+ *(?:&lt;) *@?\w+(?:(?:&lt;)|(?:&gt;)|,|@|\w| |\.)* *(?:&gt;) *\(/)) {text = text.replace(/new +@?[\w@]+ *(?:&lt;) *@?\w+(?:(?:&lt;)|(?:&gt;)|,|@|\w| |\.)* *(?:&gt;) *\(/, "###newgeneric_{" + newgenerics.length + "}###");
        newgenerics.push(tnewgeneric[0]);
    }
    // 临时排除显式类型转换中的一般类型
    var converts = new Array();
    var tconvert = null;
    while (tconvert = text.match(/\( *@?\w+ *\)@?\w+/)) {text = text.replace(/\( *@?\w+ *\)@?\w+/, "###convert_{" + converts.length + "}###");
        converts.push(tconvert[0]);
    }
    // 临时排除办法的返回类型
    var methods = new Array();
    var tmethod = null;
    while (tmethod = text.match(/@?\w+(?=(?: *\[ *\])? +@?\w+ *\()/)) {text = text.replace(/@?\w+(?=(?: *\[ *\])? +@?\w+ *\()/, "###method_{" + methods.length + "}###");
        methods.push(tmethod[0]);
    }
    // 临时排除运算符重载办法的返回类型
    var operators = new Array();
    var toperator = null;
    while (toperator = text.match(/@?\w+(?= +operator +. *\()/)) {text = text.replace(/@?\w+(?= +operator +. *\()/, "###operator_{" + operators.length + "}###");
        operators.push(toperator[0]);
    }
    // 临时排除泛型办法的返回类型
    var gmethods = new Array();
    var tgmethod = null;
    while (tgmethod = text.match(/@?\w+(?= +@?\w+(?:&lt;)@?\w+(?:&gt;) *\()/)) {text = text.replace(/@?\w+(?= +@?\w+(?:&lt;)@?\w+(?:&gt;) *\()/, "###gmethod_{" + gmethods.length + "}###");
        gmethods.push(tgmethod[0]);
    }
    // 还原并着色类申明与定义局部
    for (var i = 0; i < classes.length; i++) {var leftText = classes[i].substr(0, classes[i].match(/class\s+/)[0].length);
        var keyword = classes[i].substr(leftText.length);
        var coloredText = leftText + "<strong style=\"color:"+ colorObj.classColor +";\">" + keyword + "</strong>";
        t_regex = new RegExp("###class_\\{" + i + "\\}###");
        text = text.replace(t_regex, coloredText);
    }
    // 还原并着色构造申明与定义局部
    for (var i = 0; i < structs.length; i++) {var leftText = structs[i].substr(0, structs[i].match(/struct\s+/)[0].length);
        var keyword = structs[i].substr(leftText.length);
        var coloredText = leftText + "<strong style=\"color:"+ colorObj.classColor +";\">" + keyword + "</strong>";
        t_regex = new RegExp("###struct_\\{" + i + "\\}###");
        text = text.replace(t_regex, coloredText);
    }
    // 还原并着色接口申明与定义局部
    for (var i = 0; i < interfaces.length; i++) {var leftText = interfaces[i].substr(0, interfaces[i].match(/interface\s+/)[0].length);
        var keyword = interfaces[i].substr(leftText.length);
        var coloredText = leftText + "<strong style=\"color:"+ colorObj.classColor +";\">" + keyword + "</strong>";
        t_regex = new RegExp("###interface_\\{" + i + "\\}###");
        text = text.replace(t_regex, coloredText);
    }
    // 还原并着色异样捕捉的类型
    for (var i = 0; i < exceptions.length; i++) {
        var leftText = "";
        if (exceptions[i].indexOf(".") >= 0) {leftText = exceptions[i].substring(0, exceptions[i].lastIndexOf(".") + 1);
        } else {leftText = exceptions[i].substr(0, exceptions[i].match(/catch\s*\(\s*/)[0].length);
        }
        var keyword = exceptions[i].substr(leftText.length);
        var coloredText = leftText + "<strong style=\"color:"+ colorObj.classColor +";\">" + keyword + "</strong>";
        t_regex = new RegExp("###exception_\\{" + i + "\\}###");
        text = text.replace(t_regex, coloredText);
    }
    // 还原并着色 foreach 遍历的类型
    for (var i = 0; i < foreachs.length; i++) {
        var leftText = "";
        if (foreachs[i].indexOf(".") >= 0) {leftText = foreachs[i].substring(0, foreachs[i].lastIndexOf(".") + 1);
        } else {leftText = foreachs[i].substr(0, foreachs[i].match(/foreach\s*\(\s*/)[0].length);
        }
        var keyword = foreachs[i].substr(leftText.length);
        var coloredText = leftText + "<strong style=\"color:"+ colorObj.classColor +";\">" + keyword + "</strong>";
        t_regex = new RegExp("###foreach_\\{" + i + "\\}###");
        text = text.replace(t_regex, coloredText);
    }
    // 还原并着色 is 表达式后的类型
    for (var i = 0; i < ises.length; i++) {
        var leftText = "";
        if (ises[i].indexOf(".") >= 0) {leftText = ises[i].substring(0, ises[i].lastIndexOf(".") + 1);
        } else {leftText = ises[i].substr(0, ises[i].match(/is\s+/)[0].length);
        }
        var keyword = ises[i].substr(leftText.length);
        var coloredText = leftText + "<strong style=\"color:"+ colorObj.classColor +";\">" + keyword + "</strong>";
        t_regex = new RegExp("###is_\\{" + i + "\\}###");
        text = text.replace(t_regex, coloredText);
    }
    // 还原并着色 as 表达式后的类型
    for (var i = 0; i < ases.length; i++) {
        var leftText = "";
        if (ases[i].indexOf(".") >= 0) {leftText = ases[i].substring(0, ases[i].lastIndexOf(".") + 1);
        } else {leftText = ases[i].substr(0, ases[i].match(/as\s+/)[0].length);
        }
        var keyword = ases[i].substr(leftText.length);
        var coloredText = leftText + "<strong style=\"color:"+ colorObj.classColor +";\">" + keyword + "</strong>";
        t_regex = new RegExp("###as_\\{" + i + "\\}###");
        text = text.replace(t_regex, coloredText);
    }
    // 还原并着色事件申明与定义局部
    for (var i = 0; i < events.length; i++) {var leftText = events[i].substr(0, events[i].match(/event\s+/)[0].length);
        var keyword = events[i].substr(leftText.length);
        var coloredText = leftText + "<strong style=\"color:"+ colorObj.classColor +";\">" + keyword + "</strong>";
        t_regex = new RegExp("###event_\\{" + i + "\\}###");
        text = text.replace(t_regex, coloredText);
    }
    // 还原并着色类型申明与初始化
    for (var i = 0; i < types.length; i++) {
        var skip = false;
        for (var j = 0; j < colorObj.keywordsInfo.length; j++) {if (colorObj.keywordsInfo[j].keywords.indexOf(types[i]) >= 0) {
                skip = true;
                break;
            }
        }
        // 对关键字进行排除
        if (skip) {var originText = types[i];
            t_regex = new RegExp("###type_\\{" + i + "\\}###");
            text = text.replace(t_regex, originText);
        } else {var coloredText = "<strong style=\"color:"+ colorObj.classColor +";\">" + types[i] + "</strong>";
            t_regex = new RegExp("###type_\\{" + i + "\\}###");
            text = text.replace(t_regex, coloredText);
        }
    }
    // 还原并着色 new 关键字的类型实例化
    for (var i = 0; i < newes.length; i++) {
        var skip = false;
        for (var j = 0; j < colorObj.keywordsInfo.length; j++) {t_regex = new RegExp("new +");
            var keyword = newes[i].replace(t_regex, "");
            if (keyword.indexOf(".") >= 0) {keyword = keyword.substr(keyword.indexOf(".") + 1);
            }
            keyword = keyword.substr(0, keyword.search(/[\(\[]/));
            if (colorObj.keywordsInfo[j].keywords.indexOf(keyword) >= 0) {
                skip = true;
                break;
            }
        }
        // 对关键字进行排除
        if (skip) {var originText = newes[i];
            t_regex = new RegExp("###new_\\{" + i + "\\}###");
            text = text.replace(t_regex, originText);
        } else {
            var leftText = "", keyword ="";
            if (newes[i].indexOf(".") >= 0) {leftText = newes[i].substring(0, newes[i].lastIndexOf(".") + 1);
                keyword = newes[i].substring(newes[i].lastIndexOf(".") + 1, newes[i].search(/[\(\[]/));
            } else {leftText = newes[i].substring(0, newes[i].match(/new\s+/)[0].length);
                keyword = newes[i].substring(leftText.length + newes[i].lastIndexOf(".") + 1, newes[i].search(/[\(\[]/));
            }
            var rightText = newes[i].substring(newes[i].lastIndexOf(keyword) + keyword.length);
            var coloredText = leftText + "<strong style=\"color:"+ colorObj.classColor +";\">" + keyword + "</strong>" + rightText;
            t_regex = new RegExp("###new_\\{" + i + "\\}###");
            text = text.replace(t_regex, coloredText);
        }
    }
    // 还原并着色泛型申明
    for (var i = 0; i < genericsl.length; i++) {var coloredText = "<strong style=\"color:"+ colorObj.classColor +";\">" + genericsl[i] + "</strong>";
        t_regex = new RegExp("###genericl_\\{" + i + "\\}###");
        text = text.replace(t_regex, coloredText);
    }
    // 还原并着色 new 关键字的泛型实例化
    for (var i = 0; i < newgenerics.length; i++) {var originText = newgenerics[i];
        var coloredText = "";
        var tnewgeneric = null;
        while (tnewgeneric = originText.match(/@?\w+(?=(?: *&lt;))/)) {coloredText = "<strong style=\"color:"+ colorObj.classColor +";\">" + tnewgeneric[0] + "</strong>";
            originText = originText.replace(/@?\w+(?=(?: *&lt;))/, coloredText);
        }
        t_regex = new RegExp("###newgeneric_\\{" + i + "\\}###");
        text = text.replace(t_regex, originText);
    }
    // 临时排除 default 表达式中的类型
    var defaults = new Array();
    var tdefault = null;
    while (tdefault = text.match(/default *\([@\.\w]+/)) {text = text.replace(/default *\([@\.\w]+/, "###default_{" + defaults.length + "}###");
        defaults.push(tdefault[0]);
    }
    // 临时排除单对泛型括号中的类型
    var agbrackets = new Array();
    var tagbrackets = null;
    while (tagbrackets = text.match(/&lt; *[\.,\w@]+ *&gt;/)) {text = text.replace(/&lt; *[\.,\w@]+ *&gt;/, "###agbrackets_{" + agbrackets.length + "}###");
        agbrackets.push(tagbrackets[0]);
    }
    // 还原并着色单对泛型括号中的类型
    for (var i = 0; i < agbrackets.length; i++) {var leftText = agbrackets[i].substr(0, agbrackets[i].match(/&lt;\s*/)[0].length);
        var rightText = agbrackets[i].substr(agbrackets[i].search(/&gt;\s*/));
        agbrackets[i] = agbrackets[i].replace(leftText, "").replace(rightText,"");
        var gtypes = agbrackets[i].split(",");
        var coloredText = "";
        for (var x = 0; x < gtypes.length; x++) {
            var skip = false;
            for (var j = 0; j < colorObj.keywordsInfo.length; j++) {if (colorObj.keywordsInfo[j].keywords.indexOf(gtypes[x].trim()) >= 0) {
                    skip = true;
                    break;
                }
            }
            // 对关键字进行排除
            if (skip) {coloredText += gtypes[x] + ",";
            } else {
                var keyword = "";
                if (gtypes[x].lastIndexOf(".") >= 0) {var namespace = gtypes[x].substring(0, gtypes[x].lastIndexOf(".") + 1);
                    coloredText += namespace;
                    keyword = gtypes[x].substr(gtypes[x].lastIndexOf(".") + 1);
                } else {keyword = gtypes[x];
                }
                coloredText += "<strong style=\"color:"+ colorObj.classColor +";\">" + keyword + "</strong>,";
            }
        }
        coloredText = coloredText.substr(0, coloredText.length - 1);
        coloredText = leftText + coloredText + rightText;
        t_regex = new RegExp("###agbrackets_\\{" + i + "\\}###");
        text = text.replace(t_regex, coloredText);
    }
    // 还原并着色 default 表达式中的类型
    for (var i = 0; i < defaults.length; i++) {
        var keyword = "", leftText ="";
        var skip = false;
        for (var j = 0; j < colorObj.keywordsInfo.length; j++) {if (defaults[i].indexOf(".") >= 0) {leftText = defaults[i].substring(0, defaults[i].lastIndexOf(".") + 1);
                keyword = defaults[i].substr(defaults[i].lastIndexOf(".") + 1);
            } else {leftText = defaults[i].substr(0, defaults[i].match(/default\s*\(/)[0].length);
                keyword = defaults[i].substr(leftText.length);
            }
            if (colorObj.keywordsInfo[j].keywords.indexOf(keyword.replace(/\s/g, "")) >= 0) {
                skip = true;
                break;
            }
        }
        // 对关键字进行排除
        if (skip) {var originText = defaults[i];
            t_regex = new RegExp("###default_\\{" + i + "\\}###");
            text = text.replace(t_regex, originText);
        } else {
            var coloredText = leftText + "<strong style=\"color:"+ colorObj.classColor +";\">" + keyword + "</strong>";
            t_regex = new RegExp("###default_\\{" + i + "\\}###");
            text = text.replace(t_regex, coloredText);
        }
    }
    // 还原并着色显式类型转换中的一般类型
    for (var i = 0; i < converts.length; i++) {
        var keyword = "", leftText ="", rightText = "";
        var skip = false;
        for (var j = 0; j < colorObj.keywordsInfo.length; j++) {leftText = converts[i].substr(0, converts[i].match(/\(/)[0].length);
            keyword = converts[i].substring(leftText.length, converts[i].lastIndexOf(")"));
            rightText = converts[i].substr(converts[i].lastIndexOf(")"));
            if (colorObj.keywordsInfo[j].keywords.indexOf(keyword.replace(/\s/g, "")) >= 0) {
                skip = true;
                break;
            }
        }
        // 对关键字进行排除
        if (skip) {var originText = converts[i];
            t_regex = new RegExp("###convert_\\{" + i + "\\}###");
            text = text.replace(t_regex, originText);
        } else {
            var coloredText = leftText + "<strong style=\"color:"+ colorObj.classColor +";\">" + keyword + "</strong>" + rightText;
            t_regex = new RegExp("###convert_\\{" + i + "\\}###");
            text = text.replace(t_regex, coloredText);
        }
    }
    // 还原并着色办法的返回类型
    for (var i = 0; i < methods.length; i++) {
        var skip = false;
        for (var j = 0; j < colorObj.keywordsInfo.length; j++) {if (colorObj.keywordsInfo[j].keywords.indexOf(methods[i]) >= 0) {
                skip = true;
                break;
            }
        }
        // 对关键字进行排除
        if (skip) {var originText = methods[i];
            t_regex = new RegExp("###method_\\{" + i + "\\}###");
            text = text.replace(t_regex, originText);
        } else {var coloredText = "<strong style=\"color:"+ colorObj.classColor +";\">" + methods[i] + "</strong>";
            t_regex = new RegExp("###method_\\{" + i + "\\}###");
            text = text.replace(t_regex, coloredText);
        }
    }
    // 还原并着色运算符重载办法的返回类型
    for (var i = 0; i < operators.length; i++) {
        var skip = false;
        for (var j = 0; j < colorObj.keywordsInfo.length; j++) {if (colorObj.keywordsInfo[j].keywords.indexOf(operators[i]) >= 0) {
                skip = true;
                break;
            }
        }
        // 对关键字进行排除
        if (skip) {var originText = operators[i];
            t_regex = new RegExp("###operator_\\{" + i + "\\}###");
            text = text.replace(t_regex, originText);
        } else {var coloredText = "<strong style=\"color:"+ colorObj.classColor +";\">" + operators[i] + "</strong>";
            t_regex = new RegExp("###operator_\\{" + i + "\\}###");
            text = text.replace(t_regex, coloredText);
        }
    }
    // 还原并着色泛型办法的返回类型
    for (var i = 0; i < gmethods.length; i++) {
        var skip = false;
        for (var j = 0; j < colorObj.keywordsInfo.length; j++) {if (colorObj.keywordsInfo[j].keywords.indexOf(gmethods[i]) >= 0) {
                skip = true;
                break;
            }
        }
        // 对关键字进行排除
        if (skip) {var originText = gmethods[i];
            t_regex = new RegExp("###gmethod_\\{" + i + "\\}###");
            text = text.replace(t_regex, originText);
        } else {var coloredText = "<strong style=\"color:"+ colorObj.classColor +";\">" + gmethods[i] + "</strong>";
            t_regex = new RegExp("###gmethod_\\{" + i + "\\}###");
            text = text.replace(t_regex, coloredText);
        }
    }
    // 关键字着色
    for (var i = 0; i < colorObj.keywordsInfo.length; i++) {for (var j = 0; j < colorObj.keywordsInfo[i].keywords.length; j++) {t_regex = new RegExp("\\b" + colorObj.keywordsInfo[i].keywords[j] + "\\b", "g");
            var coloredText = "<strong style=\"color:"+ colorObj.keywordsInfo[i].color +";\">" + colorObj.keywordsInfo[i].keywords[j] + "</strong>";
            text = text.replace(t_regex, coloredText);
        }
    }
    // 自定义额定类型着色(动态类、枚举等间接成员拜访)for (var i = 0; i < colorObj.customClassInfo.length; i++) {for (var j = 0; j < colorObj.customClassInfo[i].keywords.length; j++) {t_regex = new RegExp(colorObj.customClassInfo[i].keywords[j] + "(?= *\\. *@?\\w+)", "g");
            var coloredText = "<strong style=\"color:"+ colorObj.customClassInfo[i].color +";\">" + colorObj.customClassInfo[i].keywords[j] + "</strong>";
            text = text.replace(t_regex, coloredText);
        }
    }
    // 还原并着色非空字符串
    for (var i = 0; i < strings.length; i++) {var coloredText = "<strong style=\"color:"+ colorObj.stringColor +";\">" + strings[i] + "</strong>";
        t_regex = new RegExp("###str_\\{" + i + "\\}###");
        text = text.replace(t_regex, coloredText);
    }
    // 还原并着色非空字符
    for (var i = 0; i < chars.length; i++) {var coloredText = "<strong style=\"color:"+ colorObj.stringColor +";\">" + chars[i] + "</strong>";
        t_regex = new RegExp("###char_\\{" + i + "\\}###");
        text = text.replace(t_regex, coloredText);
    }
    // 还原并着色单行正文
    for (var i = 0; i < annotations.length; i++) {
        // 还原单行正文中的字符串
        var t_string = null;
        while (t_string = annotations[i].match(/###str_\{(\d+)\}###/)) {annotations[i] = annotations[i].replace(/###str_\{(\d+)\}###/, strings[t_string[1]]);
        }
        // 还原单行正文中的多行正文
        var t_comment = null;
        while (t_comment = annotations[i].match(/###comment_\{(\d+)\}###/)) {annotations[i] = annotations[i].replace(/###comment_\{(\d+)\}###/, comments[t_comment[1]]);
        }
        var coloredText = "<strong style=\"color:"+ colorObj.annotationColor +";\">" + annotations[i] + "</strong>";
        t_regex = new RegExp("###annotation_\\{" + i + "\\}###");
        text = text.replace(t_regex, coloredText);
    }
    // 还原并着色多行正文
    for (var i = 0; i < comments.length; i++) {
        // 还原多行正文中的字符串
        var t_string = null;
        while (t_string = comments[i].match(/###str_\{(\d+)\}###/)) {comments[i] = comments[i].replace(/###str_\{(\d+)\}###/, strings[t_string[1]]);
        }
        var coloredText = "<strong style=\"color:"+ colorObj.annotationsColor +";\">" + comments[i] + "</strong>";
        t_regex = new RegExp("###comment_\\{" + i + "\\}###");
        text = text.replace(t_regex, coloredText);
    }
    // 还原并着色预处理器指令
    for (var i = 0; i < precompiles.length; i++) {
        // 还原预处理器指令中的其它项
        var t_string = null;
        while (t_string = precompiles[i].match(/###str_\{(\d+)\}###/)) {precompiles[i] = precompiles[i].replace(/###str_\{(\d+)\}###/, strings[t_string[1]]);
        }
        var t_annotation = null;
        while (t_annotation = precompiles[i].match(/###annotation_\{(\d+)\}###/)) {precompiles[i] = precompiles[i].replace(/###annotation_\{(\d+)\}###/, annotations[t_annotation[1]]);
        }
        var t_comment = null;
        while (t_comment = precompiles[i].match(/###comment_\{(\d+)\}###/)) {precompiles[i] = precompiles[i].replace(/###comment_\{(\d+)\}###/, comments[t_comment[1]]);
        }
        var coloredText = "<strong style=\"color:"+ colorObj.pragmaColor +";\">" + precompiles[i] + "</strong>";
        t_regex = new RegExp("###precompile_\\{" + i + "\\}###");
        text = text.replace(t_regex, coloredText);
    }
    return text;
}

程序的主入口就是代码中的 StainColor 办法,这个办法输出要进行语法着色的文本和要应用的着色数据,返回着色后的文本,着色后的文本是由一般文本加上 HTML 标签组合而成,如 <strong style=”color: rgb(86,156,214);”>int</strong> x;,应用办法如 StainColor(“int x;”, Colors.CSharpDark)。为了可维护性,着色用的数据曾经集成在了 Colors 对象,其中色彩相干的数据能够间接更改,还有关键字汇合(keywords)中的数据能够自在增减,关键字汇合是依照色彩进行分类的,所以依照 keywordsInfo 等数组的格局也能够进行色彩的增减,这样就能够轻松扩大为各种色彩的关键字高亮,还有几个 Colors 对象,我别离加在了另外的相干文章里,也包含其它语言的语法高亮逻辑。

程序中实现着色的中心思想是代换,次要的字符替换办法为正则表达式,针对不同的高亮语言进行了定制化的开发,这样可能确保比较完善的语法高亮,不过同时也存在一些不容忽视的 性能问题 。代换比方对 C# 进行着色时,首先对可能的语法进行暂时性的排除,在排除的过程还要对现有的关键字进行遍历过滤,这个程序中代换所用的标识格局相似于 ###name_{0}### 这样,标识的长度自身就会造成一些性能问题,在暂时性的排除过后就会应用标识对临时排除的语法进行着色和还原,一般来讲定制化的内容越多,对性能的要求就越大。因为贮存临时排除的内容须要耗费一部分内存资源,正则表达式的查问须要耗费很多处理器资源,在客户端应用的过程中,浏览器的绘制与出现自身也是一项资源耗费。我大略测试了一下,在内存时钟为 2133 MHz、最大处理器时钟为 3.5 GHz 的 Internet Explorer 浏览器下对于 40 KB 的 C# 代码进行语法着色,须要 1 ~ 2 秒左右的工夫,也就是说这个程序还 并不适宜用于即时性的语法着色,比方代码编辑中的实时着色,但一般来讲能够很好的用于根本的动态代码出现,C# 的话成果如下图:

截止目前来看,大部分的浏览器还不反对正则表达式中的反向预测(我当初只在 Chrome 浏览器中测试胜利),所以程序中有个别中央采取了 Internet Explorer 兼容形式,看上去并不是那么简洁,这或者也影响了一部分的性能。至于对性能的晋升,能够思考砍掉一些不罕用的着色,或者是缩小一些不罕用的关键字,又或者是放弃低浏览器版本的兼容性。

正文完
 0