Article-better Layout
Source code download
DP. syntaxhighlighter Code Analysis
DP. syntaxhighlighter is widely used as a commonly used JavaScript code highlighting tool.
Do you want to know its internal implementation mechanism? After analyzing it, this article extracts the core code to reproduce its function.
Note: The Code highlighted in this article uses a simplified version of the manually created DP. syntaxhighlighter.
Core Ideology
1. first, a series of regular expressions are defined to match all highlighted codes, including keywords, single-line comments, multi-line comments, and strings. if you carefully observe the highlighted JavaScript code, you will find that only these codes are highlighted, isn't it easy.
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] *? \ */', '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. Next we need to use the regular match in JavaScript to find all the matching items.
For (VAR I = 0; I <regexlist. length; I ++) {var match = NULL; while (match = regexlistpolici2.16.regex.exe C (source ))! = NULL) {matchs. Push ({value: Match [0], index: Match. index, Length: Match [0]. length, CSS: regexlistpolici#.css });}}
3. Sort the matching items (in the order in the original code)
Function sortcallback (M1, M2) {If (m1.index <m2.index) Return-1; else if (m1.index> m2.index) return 1; else {return 0 ;}} matchs = matchs. sort (sortcallback );
4. At last, take the matching items in the sorted order and integrate them with the original code.
Notes
After obtaining the list of matched items after sorting, it cannot be integrated with the original code, because there are repeated items, such:
VaR KEYWORDS = 'abstract Boolean break ';
The following match items are found: var, 'abstract Boolean Break', abstract, Boolean, and break, one of which is a string and four keywords.
In this case, we must also repeat the matching items at first.
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 <matchs [I]. index + matchs [I]. length) {return true ;}}return false;} For (VAR I = 0; I <matchs. length; I ++) {If (isinlcude (matchs, I) {matchs [I] = NULL ;}}
ModifiedSource code
Here we only process Javascript. For code in other languages, we only need to define different regular expression matching.
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] *? \ */', '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 if (m1.index> m2.index) return 1; else {return 0 ;}} function isinlcude (matchs, index) {v Ar match = matchs [Index]; for (VAR I = index-1; I> = 0; I --) {If (matchs [I]) {If (match. index> matchs [I]. index & match. index <matchs [I]. index + matchs [I]. length) {return true ;}}return false;} function convertspace (STR) {return Str. replace (/\ t/g ,""). replace (// G, "") ;}for (VAR I = 0; I <regexlist. length; I ++) {var match = NULL; while (match = regexlistpolici2.16.regex.exe C (source ))! = NULL) {matchs. push ({value: Match [0], index: match. index, Length: Match [0]. length, CSS: regexlistpolici2.16.css}) ;}} if (matchs. length) {matchs = matchs. sort (sortcallback); // remove duplicate for (VAR I = 0; I <matchs. length; I ++) {If (isinlcude (matchs, I) {matchs [I] = NULL ;}} var I = 0; For (VAR J = 0; j <matchs. length; j ++) {var match = matchs [J]; If (MATCH) {If (match. index> I) {result. push ('<sp An> '+ convertspace (source. substr (I, match. index-I) + '</span>');} result. push ('<SPAN class = "' + match.css + '">' + convertspace (match. value) + '</span>'); 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 ('<Div class = "DP-highlighter"> <ol start = "1" class = "DP-c">'); For (VAR I = 0; I <resultlines. length; I ++) {out. push (ALT? '<Li class = "Alt">': '<li>'); out. push ('<span>'); out. push (resultlines [I] = ""? "": Resultlines [I]); Out. Push ('</span>'); Out. Push ('</LI>'); Alt =! ALT;} Out. push ('</OL> </div>'); Return out. join ("") ;}$ (function () {$ ("pre. JS "). each (function () {var $ this = $ (this); incluthis.hide().after(hightlight({this.html ()));});});