// Script Coloration Syntaxique HTML, CSS, JavaScript, PHP

function Init() {
	ColoreCode();
}

/*
 * Colorer le code en (SelColore) :
 * 0 -> les 4 languages confondu ( effectué s'il croise leur tag correspondant )
 * 1 -> HTML
 * 2 -> CSS
 * 3 -> JavaScript
 * 4 -> PHP
 * 5 -> Nothing
 *
 * Numéroter les lignes (Num):
 * true -> numérote les lignes + souligne la ligne au passage de la sourie
 * false -> ne numérote pas les lignes
 *
 * Src => texte source
 * Dest => l'objet de destination prêt a recevoir le code Html
 *
 */

function ColoreCode(Src, Dest, SelColore, Num) {
	
	var tms = new Date(); 
	var tpsDep = tms.getTime(); /* date en ms */
	
	parent.NbLn = 0; /* Compteur de Ligne */
	
	var text = ColorSrc(Src, SelColore, Num);
	if (Num) {
		text = '<table cellpadding="0" cellspacing="0" class="CodeSource">'+addNumLn(text)+'</table>';
	} else {
		text = '<code id="CodeSource" class="CodeSource">'+text+'</code>';
	}
	
	Dest.innerHTML = text;
	
	tms = new Date();
	var tpsFin = tms.getTime();
	
	/** Commenter les 4 lignes si vous n'en voulez pas **/
	try {
		document.getElementById('CODE_TimeStamp').innerHTML = 'Execution Time : '+((tpsFin-tpsDep)/1000)+' Seconds for '+parent.NbLn+' Lines.';
	} catch(e) {
		alert('Execution Time : '+((tpsFin-tpsDep)/1000)+' Seconds\r\nTotal lines : '+parent.NbLn);
	}
	
	return false;
	
}

function ColorSrc(s, Sel, Num) {
	
	t = RemoveChar(s);
	
	switch(Sel) {
		case 0:
			t = t.replace(/(&lt;style.*?&gt;)(.*?)(&lt;\/style&gt;)/gim, function(st) { return '<CODE_CSS>'+ColorCSS(st)+'</CODE_CSS>';} ); // style CSS
			t = t.replace(/(&lt;script.*?&gt;)(.*?)(&lt;\/script&gt;)/gi, function(st) { return '<CODE_JS>'+ColorJSC(st)+'</CODE_JS>';} ); // javascript
			t = t.replace(/(&lt;\?.*?\?&gt;)/gi, function(st) { return '<CODE_PHP>'+ColorPHP(st)+'</CODE_PHP>';} ); // Code PHP
			t = t.replace(/(&lt;html.*?&lt;\/html&gt;)/gi, function(st) { return '<CODE_HTM>'+ColorHTML(st)+'</CODE_HTM>';} ); // html
			t = t.replace(/<(CODE_HTM|CODE_CSS|CODE_JS|CODE_CSS|CODE_PHP)>/g, '<span class="$1">');
			t = t.replace(/<\/(CODE_HTM|CODE_CSS|CODE_JS|CODE_CSS|CODE_PHP)>/g, '</span>');
			break;
		case 1:
			t = '<span class="CODE_HTM">'+ColorHTML(t)+'</span>';
			break;
		case 2:
			t = '<span class="CODE_CSS">'+ColorCSS(t)+'</span>';
			break;
		case 3:
			t = '<span class="CODE_JS">'+ColorJSC(t)+'</span>';
			break;
		case 4:
			t = '<span class="CODE_PHP">'+ColorPHP(t)+'</span>';
			break;
	}
	
	t = CleanTag(t);
	
	t = ReplaceChar(t);
	
	return t;
}

/*** Coloration Javascript ***/
function ColorJSC(s) {
	
	/* Expression Régulière */
	s = s.replace(/(\()(\/)([^\/<>]*?)(\/)([gim\)]+)/g, '$1<b>$2$3$4</b>$5'); // ça bug ...

	/* Mots réservé */
	s = s.replace(/\b(window|document|layer|self|opener|location|body|parent|screen)\b([\.\(\)])/gi, '<i>$1</i>$2');
	s = s.replace(/(\.)\b(getElementById|getElementsByTagName|getElementsByName|item|forms|element)\b([\.\[\(])/gi, '$1<em>$2</em>$3');
	s = s.replace(/\b(alert|prompt|focus|blur|open|close|find|event|navigator|submit|scroll|clearTimeout|clearInterval)\b/gi, '<big>$1</big>');
	s = s.replace(/(\.)\b(designMode|keyCode|charCode|select|text|clear|appName|value|innerHTML|innerText|match|replace|search|exec|test|write|writeln|length|substr|substring|indexOf|lastIndexOf|getSelection|left|right|down|top|width|height|offsetLeft|offsetRight|offsetTop|offsetDown|offsetWidth|offsetHeight|style|value|escape|unescape|Object|valueOf|String|toString|setTimeout|setInterval|Math|parseInt|parse|parseFloat|Array|isNaN|name|id|status|Number|addEventListener|onmouseup|onmousedown|onclick|onmouseover|onmouseout|onkeypress|onkeydown|onkeyup|onload|onunload|onblur|onfocus|onsubmit|onchange|execCommand|pasteHTML|selection|createRange|getRangeAt|createTextRange|insertNode|createElement|appendChild|removeChild|firstChild|rangeCount|childNodes|nodeType|parentElement|setAttribute|getAttribute|insertBefore|addRange|removeAllRanges|parentNode|cloneNode|nodeValue|startContanier|deleteContents|toLowerCase|toUpperCase|tagName|button|which|type)\b/gi, '$1<u>$2</u>');
	
	s = s.replace(/(\.?)\b(setTimeout|setInterval|Math|parseInt|parse|parseFloat|Array|Number|eval|RegExp)\b/gi, '$1<u>$2</u>');
	
	s = s.replace(/\b(for|if|else|switch|case|break|default|return|while|do|try|catch|throws|int|boolean|label|goto)\b/gi, '<small>$1</small>');
	s = s.replace(/\b(function|class|var|new)\b/gi, '<var>$1</var>');
	
	/* Décimaux */
	s = s.replace(/(=|\+|\*|\-|\[|\(|,|;|\s)(\s?)([\d]+)/g, '$1$2<sup>$3</sup>');
	
	// Booléen
	s = s.replace(/\b(null|true|false)\b/gi, '<s>$1</s>');
	
	// quotes double
	s = s.replace(/([\s=;\:\+\.\(\[,])(")([^"]*?)(")/g, '$1<strike>$2$3$4</strike>');
	
	// quotes simple
	s = s.replace(/([\s=;\:\+\.\(\[,])(')([^']*?)(')/g, '$1<strike>$2$3$4</strike>');
	
	// &&, ||, <=, >=, !=, += etc ... 
	s = s.replace(/(&amp;&amp;|&#124;&#124;|\!=|==|\+=|&lt;=|&gt;=|\[|\]|\{|\}|\(|\))/gi, '<s>$1</s>');
	
	// Commentaires
	s = s.replace(/(\/\*)(.*?)(\*\/)/g, '<cite>$1$2$3</cite>');
	s = s.replace(/([^:])(\/\/.*?)(<br \/>)/g, '$1<cite>$2</cite>$3');
	
	return s;
}

/*** Coloration CSS ***/
function ColorCSS(s) {
	
	/* class/tag/id:évenement */
	s = s.replace(/([A-Za-z0-9\:_\-, \.#]+)(\{)/g, function(st) { return st.replace(/([A-Za-z0-9_-]+)(\:?)([A-Za-z0-9_-]*)/g, '<s>$1</s>$2<em>$3</em>'); });
	/* Attribut:value; */
	s = s.replace(/(\s?)([A-Za-z0-9_-]+)(:)([^;\/]+?)(\s?)(;)/gi, '$1<u>$2</u>$3<i>$4</i>$5$6');
	
	/* Chaine de caractère */
	s = s.replace(/(")([^"]*?)(")/g, '<strike>$1$2$3</strike>');
	s = s.replace(/(')([^']*?)(')/g, '<strike>$1$2$3</strike>');
	
	/* Commentaire */
	s = s.replace(/(\/\*)(.*?)(\*\/)/g, function(st) { st = CleanTag(st); return '<cite>'+st+'</cite>'; });
	
	return s;
}

/*** Coloration (x)HTLM / XML ***/
function ColorHTML(s) {
	//if (s.
	// attributs="value" ( double quote )
	s = s.replace(/([A-Za-z_-]+=)(")([^"<>]*?)(")/g, '<i>$1</i><s>$2$3$4</s>');
	// attributs='value' ( simple quote )
	s = s.replace(/([A-Za-z_-]+=)(')([^'<>]*?)(')/g, '<i>$1</i><s>$2$3$4</s>');
	
	// tags
	s = s.replace(/(&lt;)(\/?)([A-Za-z0-9]+)/g, '$1$2<u>$3</u>');
	// doctype
	s = s.replace(/(&lt;!doctype)([^|]*)(&gt;)/gi, '<span class="HTM_Doc">$1$2$3</span>');
	// xml
	s = s.replace(/(&lt;\?xml)([^|]*)(&gt;)/gi, '<span class="HTM_Xml">$1$2$3</span>');
	
	// commentaires
	s = s.replace(/(&lt;\!\-\-.*?\-\-&gt;)/gi, function(h) { h = CleanTag(h);
																 	  h = h.replace(/\"/g, '&quot;');
																	  h = h.replace(/\'/g, '&#039;');
																	  return '<cite>'+h+'</cite>'; });
	
	return s;
}

/*** Coloration PHP ***/
function ColorPHP(s) {
	
	s = s.replace(/<br \/>/g, '\n');
	s = s.replace(/<\S[^><]*?>/g, '');
	s = s.replace(/\n/g, '<br \/>');
	
	// tag <?, <?php, ?>
	s = s.replace(/(&lt;\?php|&lt;\?|\?&gt;)/g, '<big>$1</big>');
	
	// Boucle, Condition, et autres ...
	s = s.replace(/\b(if|while|for|do|else|endif|endfor|endwhile|endswitch|case|return|break|case|default|echo|print_r|printf|print|exit|die|foreach|throw|try|catch)\b(\s?)/gi, '<small>$1</small>$2');
	
	// du type function truc () , class truc(), var $machin
	s = s.replace(/\b(function|var|class|global|new|static|extends|public|private)\b/g, '<i>$1</i>');
	
	// du type mysql_connect(), fopen() ...
	s = s.replace(/([A-Za-z0-9_]+)([\s]*)(\(|\{)/g, '<u>$1</u>$2$3');
	
	// les variables ( $truc );
	s = s.replace(/(\$[A-Za-z0-9_\-]+)/g, '<var>$1</var>');
	s = s.replace(/\b(this)\b(\-&gt;)/g, '<var>$&1-&gt;</var>');
	
	// les décimaux
	s = s.replace(/(=|\+|\*|\-|\[|\(| |,|;)([\d]+)/g, '$1<sup>$2</sup>');
	
	// Booléen, et caractère divers
	s = s.replace(/\b(false|true|null|and|or|xor|as)\b/g, '<em>$1</em>');
	
	s = s.replace(/(==|\!=|&amp;&amp;|&#124;&#124;|&lt;=|&gt;=|\(|\[|\]|\)|\{|\})/g, '<em>$1</em>');
	
	// Expression régulière
	s = s.replace(/(\(|=)(#|@)(.*?)(#|@)/g, '$1<b>$2$3$4</b>');
	
	// quotes double
	//s = s.replace(/(\s|\[|\(|=|\.|,)(")([^"]*)(")/g, '$1<strike>$2$3$4</strike>');
	s = s.replace(/(")([^"]*)(")/g, '<strike>$1$2$3</strike>');
	// quotes simple
	//s = s.replace(/(\s|\[|\(|=|\.|,)(')([^']*)(')/g, '$1<strike>$2$3$4</strike>');
	s = s.replace(/(')([^']*)(')/g, '<strike>$1$2$3</strike>');
	// Commentaires
	s = s.replace(/(\/\*.*?\*\/)/g, '<cite>$1</cite>');
	s = s.replace(/(\s|<br \/>)(\/\/|#)(.*?)(<br \/>)/g, '$1<cite>$2$3</cite>$4');
	
	return s;
}

function addNumLn(s) {
	
	parent.TagAdd = parent.TagEnd = parent.Class = '';
	parent.NbLn = 0;
	
	Ln = s+'<br />';
	Ln = Ln.replace(/(.*?<br \/>)/g, function(st) {
			
			parent.NbLn++;
			endTag = false;
			
			if (st.match(/<span class="[^"]*?">/)) {
				parent.Class = st.match(/<span class="([^"]*?)">/)[st.match(/<span class="([^"]*?)">/).length-1];
				st = st.replace(/<span class="[^"]*?">/g, '');
			} else if (st.indexOf('</span>') != -1) {
				parent.Class = 'CODE_HTM';
			} else if (st.indexOf('<cite>') != -1 && st.indexOf('</cite>') == -1) {
				parent.TagAdd = '<cite>';
				parent.TagEnd = '</cite>';
			} else if (st.indexOf('</cite>') != -1) {
				endTag = true;	
			}
			
			st = '<tr><td class="CODE_NumLn">'+parent.NbLn+'</td><td class="'+parent.Class+'">'+parent.TagAdd+st+parent.TagEnd+'</td></tr>';
			
			if (endTag) {
				parent.TagAdd = '';
				parent.TagEnd = '';
			}
			
			
			return st;
			
	});
	Ln = Ln.replace(/<\/span>/g, '');
	return Ln;
}
											
/** Supprime les Tags HTML inutile et/ou en trop **/
function CleanTag(s) {
		Clean = function(st1) {
					st1 = st1.replace(/<br \/>/gi, '\n');
					st1 = st1.replace(/<\S[^><]*?>/gm, '')
					st1 = st1.replace(/\n/gm, '<br />');
					return st1;
		}
		
		s = s.replace(/(<strike>.*?<\/strike>)/gi, function(st) { return '<strike>'+Clean(st)+'</strike>'; } );
		s = s.replace(/(<b>.*?<\/b>)/gi, function(st) { return '<b>'+Clean(st)+'</b>'; } );
		s = s.replace(/(<cite>.*?<\/cite>)/gi, function(st) { return '<cite>'+Clean(st)+'</cite>'; } );

		return s
}

/** Encode les caractères pouvant géner le parseur **/
function RemoveChar(s) {
	Remove = function(St) {
		St = St.replace(/&lt;/g, '&lsaquo;');
		St = St.replace(/&gt;/g, '&rsaquo;');
		return St;
	}
	
	s = s.replace(/&/gm, '&amp;');
	s = s.replace(/\|/gm, '&#124;');
	s = s.replace(/\\\//gm, '\\&#47;');
	s = s.replace(/\\\\/gm, '&#92;&#92;');
	s = s.replace(/\\/gm, '\\');
	s = s.replace(/\\'/gm, '\\&#039;');
	s = s.replace(/\\"/gm, '\\&quot;');
	s = s.replace(/</gm, '&lt;');
	s = s.replace(/>/gm, '&gt;');
	s = s.replace(/\t/gm, '          ');
	s = s.replace(/\r?\n/g, function(t) { parent.NbLn++; return '<br />'; });
	
	s = s.replace(/(\s\/\*.*?\*\/\s)/g, function(st) { st = st.replace(/\'/g, '\\&#039;'); st = st.replace(/\"/g, '\\&quot;'); return Remove(st); });
	s = s.replace(/<br \/>\/\*.*?\*\/<br \/>/g, function(st) { st = st.replace(/\'/g, '\\&#039;'); st = st.replace(/\"/g, '\\&quot;'); return Remove(st); });
	s = s.replace(/(\s\/\/)(.*?<br \/>)/g, function(st) { st = st.replace(/\'/g, '&#039;'); st = st.replace(/\"/g, '&quot;'); return Remove(st); });
	s = s.replace(/(<br \/>\/\/)(.*?<br \/>)/g, function(st) { st = st.replace(/\'/g, '&#039;'); st = st.replace(/\"/g, '&quot;'); return Remove(st); });
	s = s.replace(/([\s=;\:\+\.\(\[,])("[^"]*?")/g, function(st) { st = st.replace(/\'/g, '&#039;'); return Remove(st); });
	s = s.replace(/([\s=;\:\+\.\(\[,])('[^']*?')/g, function(st) { st = st.replace(/\"/g, '&quot;'); return Remove(st); });
	s = s.replace(/(\(\/[^\/]*?\/)/g, function(st) { st = st.replace(/'/g, '&#039;'); st = st.replace(/"/g, '&quot;'); return Remove(st); });
	
	return s;
	
}

/** Décode les caractères nécessaire dernièrement encodé **/
function ReplaceChar(s) {
	Replace = function(St) {
		St = St.replace(/&lsaquo;/g, '&lt;');
		St = St.replace(/&rsaquo;/g, '&gt;');
		St = St.replace(/&quot;/g, '"');
		St = St.replace(/&#039;/g, "'");
		St = St.replace(/  /g, "&nbsp;&nbsp;");
		St = St.replace(/> /g, ">&nbsp;");
		return St;
	}
	
	return Replace(s);
	
}