CODE HIGHLIGHTER

help and download »

This is my light weight code highlighter for html, javascript and css.

Lets review the script :-)

The color scheme

function highlightCode(codeblock,colorSet) { defaultColor = "#cccccc"; defaultBackground = "#000000"; defaultFontSet = "\'Courier New\', Times, serif"; colorScheme="#C3FF00,#8CFF00,#5DFF00,#00CE29,#00CE97,#00FFF6" if(colorSet=='blueish green'){colorScheme="#C3FF00,#8CFF00,#5DFF00,#00CE29,#00CE97,#00FFF6";} else if(colorSet=='fire'){colorScheme="#FF006E,#FF0000,#FF6A00,#FFBF00,#FFEE00,#E9FF00,#CCFF00";} else if(colorSet=='purple blue'){colorScheme="#00CBFF,#0094FF,#0065FF,#001DFF,#6A00FF,#9000FF,#C300FF,#FF00F2";} else if(colorSet=='techno') {colorScheme="#00FFD4,#00FF99,#00FF3F,#8BFF6B,#BCFF6B,#BBFF00,#83C1FC,#58DBFC,#09F5F9,#00FF8C,#A5C600,#A5C600";} else if(colorSet=='restfull') {colorScheme="#A5C600,#00C475,#00C475,#00C475,#25BC8A,#25BC8A,#25BC8A,#25BC8A,#4800FF,#6474FC,#009DFF,#A24CED,#294BE5,#317237";} else if(colorSet=='contrast') {colorScheme="#935456,#009DFF,#A24CED,#294BE5,#317237,#935456,#009DFF,#A24CED,#294BE5,#317237,#935456";} else if(colorSet=='gray shades') {colorScheme="#ffffff,#dddddd,#aaaaaa,#777777,#555555";} else if(colorSet=='haxor green') {colorScheme="#1C8E31,#16AD43,#1BD352,#18F45A,#54F284,#69D389,#A1EDB8";} else if(colorSet=='circus'){ colorScheme="#F70000,#CB00FF,#8C8AFC,#00E5FF,#00FF0C,#FAFF00,#AD7824,#E0DA86"; defaultFontSet="Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace"; } colorScheme = colorScheme.split(',');

This sets the color scheme. You can modify the colors or expand the list. The code is shown in 'blueish green'.



Load

raw = (document.getElementById(codeblock).innerHTML).split('\n').join('<br>'); raw = raw.split(' ').join(' '); colorArray = new Array(); for(long=0;long<raw.length;long++){ colorArray[long] = defaultColor; }

The line breaks in the raw code are replaced with html line breaks and the tabs are replaced with double space.

The second bit sets a default color for each character.

The code is shown in "fire".



Get the words

rawArr = raw.split(''); lowercaseRaw=raw.toLowerCase(); justletters=lowercaseRaw.replace(/[^a-z0-9]/g," "); justletters=justletters.replace(/\s+/g," ");

Here we replace everything that isn't a letter or a number with a space. Then we replace rows of spaces with single ones.

The code is shown in "purple blue".



purging the duplicates

myarray=("&lt; &gt; &amp; &amp;lt; &amp;gt; / ' { } = ( )"+' " '+justletters).split(' '); y = 0; result = new Array(); myarray=myarray.sort(); // first sort the array result[0]=myarray[0]; for(x=1;x<myarray.length;x++){ if(myarray[x]!=myarray[x-1]){ // if item is not the same as the one before result[y]=myarray[x]; // then we add it to the output array y++; } } result=result.sort(function(a,b){return a.length - b.length});

We extend the list of words with entities that should not be highlighted partially and add some special characters that we do want to colorize.

The last line sorts the array by size.

The code is shown in "techno".



Find the strings and set their colors

if(result!=-1){ for(x=0;x<result.length;x++){ locations = findInString(result[x], lowercaseRaw); if(locations!=-1){ for (ww = 0; ww < locations.length; ww++) { for(zz=0;zz<result[x].length;zz++){ if(x>=colorScheme.length){ colorScheme = colorScheme.concat(colorScheme); } colorArray[1 * locations[ww] + zz] = colorScheme[x]; } } } } }

Now we walk though our "word" list, we retreave the locations of the results, then for each result we set the color of it's letters. We start with the small strings and work our way up to the big ones. Big matches then override the small matches.

In case we run out of colors we extend the color scheme with a duplicate of the current color scheme.

The code is shown in "restfull".



Uncollor the comments

// uncolor comments // tr = lowercaseRaw; // create temporal raw copy comment = 0; // comment pointer while( tr.indexOf( '//' ) != -1){ // keep going until no instances of double slash remain comment = 1 * comment + tr.indexOf( '//' ) + 2; // increase the comment pointer to point at the next potential comment tr = lowercaseRaw.slice( comment ) + "<"; // get the part after the potential comment trB = lowercaseRaw.substring( 0 , comment ); // get the part before the potential comment trB = trB.split( '\\<br>' ).join( ' ' ); // remove escaped line breaks trB = trB.substring(trB.lastIndexOf( '>' ), trB.length); // find the beginning of the line with the potential comment sq = trB.split( "'" ).length - 1; // count the single quotes dq = trB.split( '"' ).length - 1; // count the double quotes if(sq%2 == 0 && dq%2 == 0 || sq == 1 && dq == 2 && trB.indexOf('"') < trB.indexOf("'") && trB.lastIndexOf('"') > trB.indexOf("'") || sq == 2 && dq == 1 && trB.indexOf("'") < trB.indexOf('"') && trB.lastIndexOf( "'" ) >trB.indexOf( '"' ) ){ semicol=tr.indexOf(';'); if( semicol == -1 || semicol > tr.indexOf( '<' ) ){ for( x = 0 ; x < tr.indexOf( '<' ); x++ ){ colorArray[ 1 * comment + x ] = defaultColor; } } } } // uncolor comments /* foo bar */ tr=lowercaseRaw; // create temporal raw copy comment=0; // comment pointer while(tr.indexOf('/*')!=-1){ // keep going until no instances of slash star remain comment=1*comment+tr.indexOf('/*')+2; // increase the comment pointer to point at the next potential comment tr=lowercaseRaw.slice(comment)+"<"; // get the part after the potential comment trB=lowercaseRaw.substring(0,comment); // get the part before the potential comment trB=trB.split('\\<br>').join(' '); // remove escaped line breaks trB=trB.substring(trB.lastIndexOf('>'),trB.length); // find the beginning of the line with the potential comment sq=trB.split("'").length-1; // count the single quotes dq=trB.split('"').length-1; // count the double quotes if(sq%2==0&&dq%2==0 ||sq==1&&dq==2&&trB.indexOf('"')<trB.indexOf("'")&&trB.lastIndexOf('"')>trB.indexOf("'") ||sq==2&&dq==1&&trB.indexOf("'")<trB.indexOf('"')&&trB.lastIndexOf("'")>trB.indexOf('"')){ semicol=tr.indexOf(';'); if(semicol==-1||semicol>tr.indexOf('*/')){ for(x=0;x<tr.indexOf('*/');x++){ colorArray[1*comment+x]= defaultColor; } } } }

To make them more readable we color the comments in the default color. The code is shown in "circus".



The output array pooping process

var output = '<ol start="0"><li><span style="color:'+colorArray[0]+'">'; var theOldColor = colorArray[0]; for (CharacterPointer=0;CharacterPointer<raw.length;CharacterPointer++){ theLetter=rawArr[CharacterPointer]; theColor=colorArray[CharacterPointer]; theFutureColor=colorArray[CharacterPointer*1+1]; if(theLetter=="<"){ if(lowercaseRaw.substring(CharacterPointer, (1*CharacterPointer+4))=="<br>"){ theLetter="</li><li>"; CharacterPointer=CharacterPointer*1+3; } } if (theLetter==" ") { theLetter=" <wbr>"; } if (theColor == theOldColor && theColor == theFutureColor) { output = output + theLetter; } else if (theColor == theOldColor&&CharacterPointer>1) { output = output + theLetter + '</span>'; } else if (theColor == theFutureColor) { output = output + '</span><span style="color:' + theColor + ';">' + theLetter; } else { output = output + '<span style="color:' + theColor + ';">' + theLetter + '</span>'; } theOldColor=colorArray[CharacterPointer]; }

If the color of a character is the same as the one before it there is no need to set the color. If the color of the next character is the same there is no need to close the span.

I've also made cleaver use of the wbr tag. This way we can have a kind of absolute formating without the text bursting out of the side of the monitor.

The code is shown in "contrast".



Writing it back to the page

document.getElementById(codeblock).innerHTML = '<div style="font-weight:bold;font-family:\'Courier New\', Times, serif;color:'+defaultColor+';font-size:14px;padding:4px 0px 4px 4px;background-color:'+defaultBackground+';"><ol start="0"><li>'+output+"</li></ol></div>";

We dont need that much CSS, attching a stylesheet thingy seems exessive.

The code is shown in "gray shades".



The find string inside string function

function findInString(searchFor, searchIn) { var results = new Array(); var yy = 0; var aa = searchIn.indexOf(searchFor); results[0] = aa; searchIn = searchIn.slice(aa * 1 + searchFor.length); yy = aa * 1 + searchFor.length; if (aa != -1) { for (xx = 1; searchIn.indexOf(searchFor) != -1; xx++) { yy = searchIn.indexOf(searchFor) results[xx] = 1 * results[1 * xx - 1] + searchIn.indexOf(searchFor) + searchFor.length; searchIn = searchIn.slice(1 * searchIn.indexOf(searchFor) + searchFor.length); } } return results; }

We give the function 2 strings, it searches for the first one inside the second one then it returns an array of locations where a match was found.

The code is shown in "haxor green". Nostalgica isn't trying to win any usability contest.

I'm sure by now you understand I've given you a really powerful tool here, use it wizely, we wouldn't want anyone to get hurt.



Pro tip

Besides from converting the script on the page you could also build the highlighter into your cms and have it do the formatting before you post things.



credits









GO-HERE.NL