Highlighted forum codeblocks

BlitzMax Forums/BlitzMax Programming/Highlighted forum codeblocks

I just modified this code, added a link at the bottom of the newly created code blocks that allows you to select the code.

// ==UserScript==
// @name	BlitzMax Code Highlighting
// @description Highlights BlitzMax code within codeblocks in the forums at blitzbasic.com
// @include http://blitzmax.com/*
// @include http://blitzbasic.com/*
// @include http://www.blitzmax.com/*
// @include http://www.blitzbasic.com/*
// ==/UserScript==

// keywords
var vartypes = [ "\$", "\!", "\%", "\#", "Byte", "Short", "Int", "Long", "Float", "Double", "String", "Object" ];

var keywords = [ "Strict","SuperStrict","End","True","False","Null","Pi","Nan","Var","Ptr","If","Then","Else","ElseIf","EndIf","For","To","Step","Next","EachIn",
"While","Wend","EndWhile","Repeat","Until","Forever","Select","EndSelect","Case","Default","Exit","Continue","Const","Local","Global",
"Field","Function","EndFunction","Type","EndType","Extends","Method","EndMethod","Abstract","Final","New","Self","Super","Delete",
"Release","Public","Private","Extern","EndExtern","Module","ModuleInfo","Incbin","IncbinPtr","IncbinLen","Include","Framework","Import",
"Assert","Goto","Try","EndTry","Catch","Throw","DefData","ReadData","RestoreData","And","Or","Not","Shl","Shr","Sar","Len","Abs","Mod",
"Sgn","Min","Max","Varptr","SizeOf","Asc","Chr","Return" ];

var blitz_mod = [ "RuntimeError", "DebugStop", "DebugLog", "AppDir", "AppFile", "AppTitle", "AppArgs", "LaunchDir", "OnEnd",
"ReadStdin", "WriteStdout", "WriteStderr", "Delay", "MilliSecs", "MemAlloc", "MemFree", "MemExtend",
"MemClear", "MemCopy", "MemMove", "GCSetMode", "GCSuspend", "GCResume", "GCCollect", "GCMemAlloced",
"GCEnter", "GCLeave", "HandleFromObject", "HandleToObject", "Print", "Input"]

function addGlobalStyle(css) {
    var head, style;
    head = document.getElementsByTagName('head')[0];
    if (!head) { return; }
    style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = css;
    head.appendChild(style);
}
// color styles use by highlighter
addGlobalStyle(
	// background & normal text styles
	"pre.code, pre.codebox { background-color: #013c77 !important;  color: #f0f0f0 !important; }" +
	"pre.codebox { border: 2px solid gray !important; }" +
	// code styles
	".code-comment { color: #06bed9 !important; font-weight: none !important;  }" +
	".code-keyword { color: #fbfb00 !important; font-weight: none !important;  }" +
	".code-vartype { color: #fbc300 !important; font-weight: none !important;  }" +
	".code-string { color: #00f400 !important; font-weight: none !important;  }" +
	".code-number { color: #bbbbbb !important; font-weight: none !important;  }" +
	".code-attribute { color: #808080 !important; font-weight: none !important;  }"
);


function HighlightWord( source, word, style) {
	return source.replace( new RegExp( "\\b("+word+")\\b", "gim"), "<font class=" + style + ">$1</font>");
}

function Sanitize( source) {
	return source.replace( /<\/?font( class=code-(comment|keyword|vartype|string|number|attribute))?(>|$)/gi, "");
}

function HighlightSource( code) {
	// vartypes
	for( var x=0; x<vartypes.length; x++)	code = HighlightWord( code, vartypes[x], "code-vartype");
	// keywords
	for( var x=0; x<keywords.length; x++)	code = HighlightWord( code, keywords[x], "code-keyword");
	for( var x=0; x<blitz_mod.length; x++)	code = HighlightWord( code, blitz_mod[x], "code-keyword");
	// numerals
	code = code.replace( /\b(\$[a-f0-9]+|%[0-1]+|\d+(\.\d*)?)\b/gi, "<font class=code-number>$1</font>");	
	// attributes
	code = code.replace( /(\{[^\r\n\}]*\})/g, function(match,p) {
		return "<font class=code-attribute>"+Sanitize(p)+"</font>";
	});
	// strings
	code = code.replace( /("[^\r\n"]*")/g, function(match,p) {
		// hack to get around comments inside strings
		var s = Sanitize(p).replace( /'/g, "=SINGLE-QUOTE=")
		return "<font class=code-string>"+s+"</font>";
	});
	// comments
	code = code.replace( /('.*)$/gm, function(match,p) {
		return "<font class=code-comment>"+Sanitize(p)+"</font>";
	});
	code = code.replace( /^(Rem(\n|.)*EndRem)$/gim, function(match,p) {
		return "<font class=code-comment>"+Sanitize(p)+"</font>";
	});
	// hack to get around comments inside strings
	return code.replace( /=SINGLE-QUOTE=/g, "'");
}

// highlight all codebox elements on the page
var codes = document.evaluate( "//pre[@class='code']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for( var i=0; i<codes.snapshotLength; i++) {
	var e = codes.snapshotItem(i);
	e.id = "greasemonkey_bbcode_"+(i+1);
	e.innerHTML = HighlightSource( e.innerHTML);
	var a = document.createElement("a");
		a.href = "#";
		a.id = "greasemonkey_bbcode_"+(i+1)+"_a"
		a.addEventListener('click', selectCodeBoxCode, false);
		a.appendChild( document.createTextNode("Select Above Code") );
		a.style.marginTop = "0";
		e.style.marginBottom = "0";
	e.parentNode.insertBefore(a, e.nextSibling);
}

var codeboxes = document.evaluate( "//textarea[@class='codebox']", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for( var i=0; i<codeboxes.snapshotLength; i++) {
	
	var e = codeboxes.snapshotItem(i);
	var c = document.createElement("pre");
	c.id = "greasemonkey_bbcodebox_"+(i+1);
	c.className = "codebox";
	c.style.overflow = "auto";
	c.style.width = 800;
	c.style.height = 300;
	c.style.fontSize = "1.5em";
	c.innerHTML = HighlightSource( e.innerHTML);
	e.parentNode.insertBefore( c, e);
	e.parentNode.removeChild(e);
	var a = document.createElement("a");
		a.href = "#";
		a.id = "greasemonkey_bbcodebox_"+(i+1)+"_a"
		a.addEventListener('click', selectCodeBoxCode, false);
		a.appendChild( document.createTextNode("Select Above Code") );
		a.style.marginTop = "0";
		c.style.marginBottom = "0";
	c.parentNode.insertBefore(a, c.nextSibling);
}

function selectCodeBoxCode(event){
	var userSelection;
	if (window.getSelection) {
		userSelection = window.getSelection();
	}	
	if (document.createRange){
		var oRange = document.createRange();
		var target = document.getElementById( this.id.substring( 0, this.id.length - 2 ) );
		oRange.selectNodeContents(target);
		userSelection.addRange(oRange);
	}
	event.preventDefault()
	return false;
}