// Title:     List Injection for PRE Tags - http://dizque.lacalabaza.net/sotanos/2005/07/lipt-inyeccion-de-listas/
// Author:    Choan C. Galvez
// Updated:   July 05

(function() { // anonymous function, doesn't pollute the global namespace
function lipt(e) {
	
	/* change to FALSE if you don't want to proccess comments */
	var PROCCESS_COMMENTS = true; 

	if (!document.getElementsByTagName) {return;}

	var ns = document.getElementsByTagName('html')[0].getAttribute('xmlns');

	// look for pre tags in the doc
	var pres = document.getElementsByTagName('pre');

	if (0 == pres.length) {
		return; // no pre tags, nothing to do
	}

	for (var i = 0; i < pres.length; i++) {
		var pre = pres[i];

		// search for the first code element inside the pre
		var code = pre.getElementsByTagName('code')[0];
		
		if (null == code) {
			continue; // no one here, try with the next pre tag
		}

		// go for the job
		var inMultiLineComment = false;
		var inHtmlComment = false;
		
		var content = getText(code);

		// normalize new lines
		if (!window.opera) { /* Opera seems to have a nice bug with global replacements */
			content = content.replace(/\n|\r|\r\n/g, '\n');
		} else {
			content = content.replace(/\n|\r|\r\n/, '\n');
		}
		content = content.replace(/^\n*/, ''); /* trim empty lines at start */
		content = content.replace(/\n*$/, ''); /* trim empty lines at the end */

		var lines = content.split('\n');

		var ol = createElement('ol', ns);
		ol.className = 'code';
		
		for (var j = 0; j < lines.length; j++) {
			var line = lines[j];
			line = line.replace(/\t/g, '    '); // replace tab with four spaces
			
			var cname = 'tab' + (Math.floor(countSpaces(line) / 4)); // className for this line
			var restSpaces = countSpaces(line) % 4;
			line = line.replace(/^ +/, '');
			if (restSpaces) {
				for (var k = 0; k < restSpaces; k++) {
					line = '\u00A0' + line; /* &nbsp; equivalent in Unicode */
				}
			}
			var parts = new Array();

			if (inMultiLineComment || inHtmlComment) {
				parts = ['', line];
			} else {
				parts = [line];
			}

			if (PROCCESS_COMMENTS) {
				var slashSlashPos = line.indexOf('//');
				var starSlashPos = line.indexOf('/*');
				var slashStarPos = line.indexOf('*/');
				var htmlCmtStart = line.indexOf('<!--');
				var htmlCmtEnd   = line.indexOf('-->');
				
				labelSlashSlash: if (slashSlashPos != -1) {
					switch (line.charAt(slashSlashPos -1)) {
						case '"':
						case "'":
						case ':': /* don't process URIs as comments */
							break labelSlashSlash;
					}
					//parts = line.split('//');
					//parts[1] = '//' + parts[1];
					parts[0] = line.substring(0, slashSlashPos);
					parts[1] = line.substring(slashSlashPos)
				} else if (starSlashPos != -1) {
					switch (line.charAt(starSlashPos -1)) {
						case '"':
						case "'":
							break labelSlashSlash;
					}
					if (!inMultiLineComment) {
						parts = line.split('/*');
						parts[1] = '/*' + parts[1];
					}
					inMultiLineComment = true;
				}

				labelHtmlCmt: if (htmlCmtStart != -1) {
					switch (line.charAt(htmlCmtStart -1)) {
						case '"':
						case "'":
							break labelHtmlCmt;
					}
					if (!inHtmlComment) {
						parts = line.split('<!--');
						parts[1] = '<!--' + parts[1];
					}
					inHtmlComment = true;
				}

				
				if (slashStarPos != -1) {
					inMultiLineComment = false;
				}

				if (htmlCmtEnd != -1) {
					inHtmlComment = false;
				}
			}

			var li = createElement('li', ns);
			
			if (j%2!=0) {
				li.className = cname + ' even';
			} else {
				li.className = cname; // tab0, tab1, etc.
			}
			
			var em = createElement('code', ns);
			var code = document.createTextNode(parts[0]); 
			em.appendChild(code);

			
			if (parts[1]) {
				var cmt = createElement('em', ns);
				cmt.appendChild(document.createTextNode(parts[1]));
				em.appendChild(cmt);
			}

			em.appendChild(document.createTextNode('\u00A0')); /* Unicode non-breaking space fix for Firefox */
			
			li.appendChild(em);
			ol.appendChild(li);
		};

		pre.parentNode.replaceChild(ol, pre);
		i--; // IMPORTANT: if we replace the pre, now there are n - 1 pre elements in the collection we are traversing
	};

	function countSpaces(s) {
		var spaceCount = 0;
		for (var i = 0; i < s.length; i++) {
			if (' ' == s.substr(i,1)) {spaceCount++;} else {break;}
		};
		return spaceCount;
	}

	function getText(node) {
		/* from JavaScript The Definitive Guide */
		var s = '';
		var children = node.childNodes;
		for (var i=0; i < children.length; i++) {
			var child = children[i];
			if (child.nodeType == 3 /* Text node */) {
				s += child.data;
			} else {
				s += getText(child);
			}
		}
		return s;
	}

	function createElement(element, ns) {
		// Adapted from Simon Willinson's code 
		// <http://simon.incutio.com/archive/2003/06/15/javascriptWithXML>
		if (ns && typeof document.createElementNS != 'undefined') {
			return document.createElementNS(ns, element);
		}
		if (typeof document.createElement != 'undefined') {
			return document.createElement(element);
		}
		return false;
	}
}

// add the handler to the onload event
var oldOnload = window.onload;
if (typeof oldOnload == 'function') {
	window.onload = function() {
		oldOnload();
		lipt();
	}
} else {
	window.onload = lipt;
}
})(); // execute