首页 > IT职业 > IT生活 > dp.SyntaxHighlighter代码分析
文章截图 - 更好的排版
源代码下载
dp.SyntaxHighlighter作为一个最常用的JavaScript代码高亮工具受到广泛的欢迎。
那么你有没有想知道它的内部实现机制是什么,本文在对其分析后,抽取核心代码以重现其功能。
注:本文中的代码高亮使用的就是手工打造的dp.SyntaxHighlighter的简化版。
核心思想
1. 首先定义了一系列的正则表达式用来匹配所有的高亮代码,包括关键字、单行注释、多行注释、字符串, 如果你仔细观察高亮后的JavaScript代码,你会发现也只有这些代码被高亮显示了,是不是很简单。
var keywords = 'abstract boolean break byte case catch char class const continue debugger ' + 'default delete do double else enum export extends false final finally float ' + 'for function goto if implements import in instanceof int interface long native ' + 'new null package private protected public return short static super switch ' + 'synchronized this throw throws transient true try typeof var void volatile while with';var regexList = [{ regex: new RegExp('/\*[\s\S]*?\*/', 'gm'), css: 'comment' },{ regex: new RegExp('//.*$', 'gm'), css: 'comment' },{ regex: new RegExp('"(?:\.|(\\\")|[^\""\n])*"', 'g'), css: 'string' },{ regex: new RegExp("'(?:\.|(\\\')|[^\''\n])*'", 'g'), css: 'string' },{ regex: new RegExp(getKeywords(keywords), 'gm'), css: 'keyword'}];function getKeywords(str) { return '\b' + str.replace(/ /g, '\b|\b') + '\b';}
2. 接下来我们需要通过JavaScript中的正则匹配来找到所有的匹配项。
for (var i = 0; i
3. 然后对匹配项进行排序(按照其在原始代码中的顺序)function sortCallback(m1, m2) { if (m1.index m2.index) return 1; else { return 0; }}matchs = matchs.sort(sortCallback);
4. 最后拿着这些排好顺序的匹配项,和原始代码进行整合就好了。
注意事项
在拿到排序后的匹配项列表后,还不能和原始代码整合,因为其中有重复项,比如:var keywords = 'abstract boolean break';会找到如下匹配项:var,'abstract boolean break',abstract,boolean,break这五个匹配项,其中一个字符串,四个关键词。
对于这样的情况,我们还必须起初重复的匹配项。function isInlcude(matchs, index) { var match = matchs[index]; for (var i = index - 1; i >= 0; i--) { if (matchs[i]) { if (match.index > matchs[i].index && match.index
修改后的源代码
这里只处理JavaScript的情况,对于其他语言的代码,只需要定义不同的正则匹配表达式就行了。function hightLight(source) { var keywords = 'abstract boolean break byte case catch char class const continue debugger ' + 'default delete do double else enum export extends false final finally float ' + 'for function goto if implements import in instanceof int interface long native ' + 'new null package private protected public return short static super switch ' + 'synchronized this throw throws transient true try typeof var void volatile while with'; var regexList = [{ regex: new RegExp('/\*[\s\S]*?\*/', 'gm'), css: 'comment' }, { regex: new RegExp('//.*$', 'gm'), css: 'comment' }, { regex: new RegExp('"(?:\.|(\\\")|[^\""\n])*"', 'g'), css: 'string' }, { regex: new RegExp("'(?:\.|(\\\')|[^\''\n])*'", 'g'), css: 'string' }, { regex: new RegExp(getKeywords(keywords), 'gm'), css: 'keyword'}]; var matchs = [], result = []; function getKeywords(str) { return '\b' + str.replace(/ /g, '\b|\b') + '\b'; } function sortCallback(m1, m2) { if (m1.index m2.index) return 1; else { return 0; } } function isInlcude(matchs, index) { var match = matchs[index]; for (var i = index - 1; i >= 0; i--) { if (matchs[i]) { if (match.index > matchs[i].index && match.index i) { result.push('' + convertSpace(source.substr(i, match.index - i)) + ''); } result.push('' + convertSpace(match.value) + ''); i = match.index + match.length; } } if (i != source.length - 1) { result.push(convertSpace(source.substr(i))); } } var resultLines = result.join("").split("n"); var out = [], alt = false; out.push(''); return out.join("");}$(function() { $("pre.js").each(function() { var $this = $(this); $this.hide().after(hightLight($this.html())); });});'); for (var i = 0; i ' : '
- '); out.push(''); out.push(resultLines[i] === "" ? " " : resultLines[i]); out.push(''); out.push('
'); alt = !alt; } out.push('
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/4759/viewspace-2806207/ ,如需转载,请注明出处,否则将追究法律责任。