src/cm/media/js/lib/yui/yui3.0.0/assets/dpSyntaxHighlighter.js
changeset 0 40c8f766c9b8
equal deleted inserted replaced
-1:000000000000 0:40c8f766c9b8
       
     1 /**
       
     2  * Code Syntax Highlighter.
       
     3  * Version 1.3.0
       
     4  * Copyright (C) 2004 Alex Gorbatchev.
       
     5  * http://www.dreamprojections.com/syntaxhighlighter/
       
     6  * 
       
     7  * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General 
       
     8  * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) 
       
     9  * any later version.
       
    10  *
       
    11  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied 
       
    12  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 
       
    13  * details.
       
    14  *
       
    15  * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to 
       
    16  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
       
    17  */
       
    18 
       
    19 //
       
    20 // create namespaces
       
    21 //
       
    22 var dp = {
       
    23 	sh :					// dp.sh
       
    24 	{
       
    25 		Utils	: {},		// dp.sh.Utils
       
    26 		Brushes	: {},		// dp.sh.Brushes
       
    27 		Strings : {},
       
    28 		Version : '1.3.0'
       
    29 	}
       
    30 };
       
    31 
       
    32 dp.sh.Strings = {
       
    33 	AboutDialog : '<html><head><title>About...</title></head><body class="dp-about"><table cellspacing="0"><tr><td class="copy"><p class="title">dp.SyntaxHighlighter</div><div class="para">Version: {V}</p><p><a href="http://www.dreamprojections.com/syntaxhighlighter/?ref=about" target="_blank">http://www.dreamprojections.com/SyntaxHighlighter</a></p>&copy;2004-2005 Alex Gorbatchev. All right reserved.</td></tr><tr><td class="footer"><input type="button" class="close" value="OK" onClick="window.close()"/></td></tr></table></body></html>',
       
    34 	
       
    35 	// tools
       
    36 	ExpandCode : '+ expand code',
       
    37 	ViewPlain : 'view plain',
       
    38 	Print : 'print',
       
    39 	CopyToClipboard : 'copy to clipboard',
       
    40 	About : '?',
       
    41 	
       
    42 	CopiedToClipboard : 'The code is in your clipboard now.'
       
    43 };
       
    44 
       
    45 dp.SyntaxHighlighter = dp.sh;
       
    46 
       
    47 //
       
    48 // Dialog and toolbar functions
       
    49 //
       
    50 
       
    51 dp.sh.Utils.Expand = function(sender)
       
    52 {
       
    53 	var table = sender;
       
    54 	var span = sender;
       
    55 
       
    56 	// find the span in which the text label and pipe contained so we can hide it
       
    57 	while(span != null && span.tagName != 'SPAN')
       
    58 		span = span.parentNode;
       
    59 
       
    60 	// find the table
       
    61 	while(table != null && table.tagName != 'TABLE')
       
    62 		table = table.parentNode;
       
    63 	
       
    64 	// remove the 'expand code' button
       
    65 	span.parentNode.removeChild(span);
       
    66 	
       
    67 	table.tBodies[0].className = 'show';
       
    68 	table.parentNode.style.height = '100%'; // containing div isn't getting updated properly when the TBODY is shown
       
    69 }
       
    70 
       
    71 // opens a new windows and puts the original unformatted source code inside.
       
    72 dp.sh.Utils.ViewSource = function(sender)
       
    73 {
       
    74 	var code = sender.parentNode.originalCode;
       
    75 	var wnd = window.open('', '_blank', 'width=750, height=400, location=0, resizable=1, menubar=0, scrollbars=1');
       
    76 	
       
    77 	code = code.replace(/</g, '&lt;');
       
    78 	
       
    79 	wnd.document.write('<pre>' + code + '</pre>');
       
    80 	wnd.document.close();
       
    81 }
       
    82 
       
    83 // copies the original source code in to the clipboard (IE only)
       
    84 dp.sh.Utils.ToClipboard = function(sender)
       
    85 {
       
    86 	var code = sender.parentNode.originalCode;
       
    87 	
       
    88 	// This works only for IE. There's a way to make it work with Mozilla as well,
       
    89 	// but it requires security settings changed on the client, which isn't by
       
    90 	// default, so 99% of users won't have it working anyways.
       
    91 	if(window.clipboardData)
       
    92 	{
       
    93 		window.clipboardData.setData('text', code);
       
    94 		
       
    95 		alert(dp.sh.Strings.CopiedToClipboard);
       
    96 	}
       
    97 }
       
    98 
       
    99 // creates an invisible iframe, puts the original source code inside and prints it
       
   100 dp.sh.Utils.PrintSource = function(sender)
       
   101 {
       
   102 	var td		= sender.parentNode;
       
   103 	var code	= td.processedCode;
       
   104 	var iframe	= document.createElement('IFRAME');
       
   105 	var doc		= null;
       
   106 	var wnd		= 
       
   107 
       
   108 	// this hides the iframe
       
   109 	iframe.style.cssText = 'position:absolute; width:0px; height:0px; left:-5px; top:-5px;';
       
   110 	
       
   111 	td.appendChild(iframe);
       
   112 	
       
   113 	doc = iframe.contentWindow.document;
       
   114 	code = code.replace(/</g, '&lt;');
       
   115 	
       
   116 	doc.open();
       
   117 	doc.write('<pre>' + code + '</pre>');
       
   118 	doc.close();
       
   119 	
       
   120 	iframe.contentWindow.focus();
       
   121 	iframe.contentWindow.print();
       
   122 	
       
   123 	td.removeChild(iframe);
       
   124 }
       
   125 
       
   126 dp.sh.Utils.About = function()
       
   127 {
       
   128 	var wnd	= window.open('', '_blank', 'dialog,width=320,height=150,scrollbars=0');
       
   129 	var doc	= wnd.document;
       
   130 	
       
   131 	var styles = document.getElementsByTagName('style');
       
   132 	var links = document.getElementsByTagName('link');
       
   133 	
       
   134 	doc.write(dp.sh.Strings.AboutDialog.replace('{V}', dp.sh.Version));
       
   135 	
       
   136 	// copy over ALL the styles from the parent page
       
   137 	for(var i = 0; i < styles.length; i++)
       
   138 		doc.write('<style>' + styles[i].innerHTML + '</style>');
       
   139 
       
   140 	for(var i = 0; i < links.length; i++)
       
   141 		if(links[i].rel.toLowerCase() == 'stylesheet')
       
   142 			doc.write('<link type="text/css" rel="stylesheet" href="' + links[i].href + '"></link>');
       
   143 	
       
   144 	doc.close();
       
   145 	wnd.focus();
       
   146 }
       
   147 
       
   148 //
       
   149 // Match object
       
   150 //
       
   151 dp.sh.Match = function(value, index, css)
       
   152 {
       
   153 	this.value		= value;
       
   154 	this.index		= index;
       
   155 	this.length		= value.length;
       
   156 	this.css		= css;
       
   157 }
       
   158 
       
   159 //
       
   160 // Highlighter object
       
   161 //
       
   162 dp.sh.Highlighter = function()
       
   163 {
       
   164 	this.addGutter = true;
       
   165 	this.addControls = true;
       
   166 	this.collapse = false;
       
   167 	this.tabsToSpaces = true;
       
   168 }
       
   169 
       
   170 // static callback for the match sorting
       
   171 dp.sh.Highlighter.SortCallback = function(m1, m2)
       
   172 {
       
   173 	// sort matches by index first
       
   174 	if(m1.index < m2.index)
       
   175 		return -1;
       
   176 	else if(m1.index > m2.index)
       
   177 		return 1;
       
   178 	else
       
   179 	{
       
   180 		// if index is the same, sort by length
       
   181 		if(m1.length < m2.length)
       
   182 			return -1;
       
   183 		else if(m1.length > m2.length)
       
   184 			return 1;
       
   185 	}
       
   186 	return 0;
       
   187 }
       
   188 
       
   189 // gets a list of all matches for a given regular expression
       
   190 dp.sh.Highlighter.prototype.GetMatches = function(regex, css)
       
   191 {
       
   192 	var index = 0;
       
   193 	var match = null;
       
   194 
       
   195 	while((match = regex.exec(this.code)) != null)
       
   196 	{
       
   197 		this.matches[this.matches.length] = new dp.sh.Match(match[0], match.index, css);
       
   198 	}
       
   199 }
       
   200 
       
   201 dp.sh.Highlighter.prototype.AddBit = function(str, css)
       
   202 {
       
   203 	var span = document.createElement('span');
       
   204 	
       
   205 	str = str.replace(/&/g, '&amp;');
       
   206 	str = str.replace(/ /g, '&nbsp;');
       
   207 	str = str.replace(/</g, '&lt;');
       
   208 	str = str.replace(/\n/gm, '&nbsp;<br>');
       
   209 
       
   210 	// when adding a piece of code, check to see if it has line breaks in it 
       
   211 	// and if it does, wrap individual line breaks with span tags
       
   212 	if(css != null)
       
   213 	{
       
   214 		var regex = new RegExp('<br>', 'gi');
       
   215 		
       
   216 		if(regex.test(str))
       
   217 		{
       
   218 			var lines = str.split('&nbsp;<br>');
       
   219 			
       
   220 			str = '';
       
   221 			
       
   222 			for(var i = 0; i < lines.length; i++)
       
   223 			{
       
   224 				span			= document.createElement('SPAN');
       
   225 				span.className	= css;
       
   226 				span.innerHTML	= lines[i];
       
   227 				
       
   228 				this.div.appendChild(span);
       
   229 				
       
   230 				// don't add a <BR> for the last line
       
   231 				if(i + 1 < lines.length)
       
   232 					this.div.appendChild(document.createElement('BR'));
       
   233 			}
       
   234 		}
       
   235 		else
       
   236 		{
       
   237 			span.className = css;
       
   238 			span.innerHTML = str;
       
   239 			this.div.appendChild(span);
       
   240 		}
       
   241 	}
       
   242 	else
       
   243 	{
       
   244 		span.innerHTML = str;
       
   245 		this.div.appendChild(span);
       
   246 	}
       
   247 }
       
   248 
       
   249 // checks if one match is inside any other match
       
   250 dp.sh.Highlighter.prototype.IsInside = function(match)
       
   251 {
       
   252 	if(match == null || match.length == 0)
       
   253 		return;
       
   254 	
       
   255 	for(var i = 0; i < this.matches.length; i++)
       
   256 	{
       
   257 		var c = this.matches[i];
       
   258 		
       
   259 		if(c == null)
       
   260 			continue;
       
   261 		
       
   262 		if((match.index > c.index) && (match.index <= c.index + c.length))
       
   263 			return true;
       
   264 	}
       
   265 	
       
   266 	return false;
       
   267 }
       
   268 
       
   269 dp.sh.Highlighter.prototype.ProcessRegexList = function()
       
   270 {
       
   271 	for(var i = 0; i < this.regexList.length; i++)
       
   272 		this.GetMatches(this.regexList[i].regex, this.regexList[i].css);
       
   273 }
       
   274 
       
   275 dp.sh.Highlighter.prototype.ProcessSmartTabs = function(code)
       
   276 {
       
   277 	var lines	= code.split('\n');
       
   278 	var result	= '';
       
   279 	var tabSize	= 4;
       
   280 	var tab		= '\t';
       
   281 
       
   282 	// This function inserts specified amount of spaces in the string
       
   283 	// where a tab is while removing that given tab. 
       
   284 	function InsertSpaces(line, pos, count)
       
   285 	{
       
   286 		var left	= line.substr(0, pos);
       
   287 		var right	= line.substr(pos + 1, line.length);	// pos + 1 will get rid of the tab
       
   288 		var spaces	= '';
       
   289 		
       
   290 		for(var i = 0; i < count; i++)
       
   291 			spaces += ' ';
       
   292 		
       
   293 		return left + spaces + right;
       
   294 	}
       
   295 
       
   296 	// This function process one line for 'smart tabs'
       
   297 	function ProcessLine(line, tabSize)
       
   298 	{
       
   299 		if(line.indexOf(tab) == -1)
       
   300 			return line;
       
   301 
       
   302 		var pos = 0;
       
   303 
       
   304 		while((pos = line.indexOf(tab)) != -1)
       
   305 		{
       
   306 			// This is pretty much all there is to the 'smart tabs' logic.
       
   307 			// Based on the position within the line and size of a tab, 
       
   308 			// calculate the amount of spaces we need to insert.
       
   309 			var spaces = tabSize - pos % tabSize;
       
   310 			
       
   311 			line = InsertSpaces(line, pos, spaces);
       
   312 		}
       
   313 		
       
   314 		return line;
       
   315 	}
       
   316 
       
   317 	// Go through all the lines and do the 'smart tabs' magic.
       
   318 	for(var i = 0; i < lines.length; i++)
       
   319 		result += ProcessLine(lines[i], tabSize) + '\n';
       
   320 	
       
   321 	return result;
       
   322 }
       
   323 
       
   324 dp.sh.Highlighter.prototype.SwitchToTable = function()
       
   325 {
       
   326 	// thanks to Lachlan Donald from SitePoint.com for this <br/> tag fix.
       
   327 	var html	= this.div.innerHTML.replace(/<(br)\/?>/gi, '\n');
       
   328 	var lines	= html.split('\n');
       
   329 	var row		= null;
       
   330 	var cell	= null;
       
   331 	var tBody	= null;
       
   332 	var html	= '';
       
   333 	var pipe	= ' | ';
       
   334 
       
   335 	// creates an anchor to a utility
       
   336 	function UtilHref(util, text)
       
   337 	{
       
   338 		return '<a href="#" onclick="dp.sh.Utils.' + util + '(this); return false;">' + text + '</a>';
       
   339 	}
       
   340 	
       
   341 	tBody = document.createElement('TBODY');	// can be created and all others go to tBodies collection.
       
   342 
       
   343 	this.table.appendChild(tBody);
       
   344 		
       
   345 	if(this.addGutter == true)
       
   346 	{
       
   347 		row = tBody.insertRow(-1);
       
   348 		cell = row.insertCell(-1);
       
   349 		cell.className = 'tools-corner';
       
   350 	}
       
   351 
       
   352 	if(this.addControls == true)
       
   353 	{
       
   354 		var tHead = document.createElement('THEAD');	// controls will be placed in here
       
   355 		this.table.appendChild(tHead);
       
   356 
       
   357 		row = tHead.insertRow(-1);
       
   358 
       
   359 		// add corner if there's a gutter
       
   360 		if(this.addGutter == true)
       
   361 		{
       
   362 			cell = row.insertCell(-1);
       
   363 			cell.className = 'tools-corner';
       
   364 		}
       
   365 		
       
   366 		cell = row.insertCell(-1);
       
   367 		
       
   368 		// preserve some variables for the controls
       
   369 		cell.originalCode = this.originalCode;
       
   370 		cell.processedCode = this.code;
       
   371 		cell.className = 'tools';
       
   372 		
       
   373 		if(this.collapse == true)
       
   374 		{
       
   375 			tBody.className = 'hide';
       
   376 			cell.innerHTML += '<span><b>' + UtilHref('Expand', dp.sh.Strings.ExpandCode) + '</b>' + pipe + '</span>';
       
   377 		}
       
   378 
       
   379 		cell.innerHTML += UtilHref('ViewSource', dp.sh.Strings.ViewPlain) + pipe + UtilHref('PrintSource', dp.sh.Strings.Print);
       
   380 		
       
   381 		// IE has this clipboard object which is easy enough to use
       
   382 		if(window.clipboardData)
       
   383 			cell.innerHTML += pipe + UtilHref('ToClipboard', dp.sh.Strings.CopyToClipboard);
       
   384 		
       
   385 		cell.innerHTML += pipe + UtilHref('About', dp.sh.Strings.About);
       
   386 	}
       
   387 
       
   388 	for(var i = 0, lineIndex = this.firstLine; i < lines.length - 1; i++, lineIndex++)
       
   389 	{
       
   390 		row = tBody.insertRow(-1);
       
   391 		
       
   392 		if(this.addGutter == true)
       
   393 		{
       
   394 			cell = row.insertCell(-1);
       
   395 			cell.className = 'gutter';
       
   396 			cell.innerHTML = lineIndex;
       
   397 		}
       
   398 
       
   399 		cell = row.insertCell(-1);
       
   400 		cell.className = 'line' + (i % 2 + 1);		// uses .line1 and .line2 css styles for alternating lines
       
   401 		cell.innerHTML = lines[i];
       
   402 	}
       
   403 	
       
   404 	this.div.innerHTML	= '';
       
   405 }
       
   406 
       
   407 dp.sh.Highlighter.prototype.Highlight = function(code)
       
   408 {
       
   409 	function Trim(str)
       
   410 	{
       
   411 		return str.replace(/^\s*(.*?)[\s\n]*$/g, '$1');
       
   412 	}
       
   413 	
       
   414 	function Chop(str)
       
   415 	{
       
   416 		return str.replace(/\n*$/, '').replace(/^\n*/, '');
       
   417 	}
       
   418 
       
   419 	function Unindent(str)
       
   420 	{
       
   421 		var lines = str.split('\n');
       
   422 		var indents = new Array();
       
   423 		var regex = new RegExp('^\\s*', 'g');
       
   424 		var min = 1000;
       
   425 
       
   426 		// go through every line and check for common number of indents
       
   427 		for(var i = 0; i < lines.length && min > 0; i++)
       
   428 		{
       
   429 			if(Trim(lines[i]).length == 0)
       
   430 				continue;
       
   431 				
       
   432 			var matches = regex.exec(lines[i]);
       
   433 
       
   434 			if(matches != null && matches.length > 0)
       
   435 				min = Math.min(matches[0].length, min);
       
   436 		}
       
   437 
       
   438 		// trim minimum common number of white space from the begining of every line
       
   439 		if(min > 0)
       
   440 			for(var i = 0; i < lines.length; i++)
       
   441 				lines[i] = lines[i].substr(min);
       
   442 
       
   443 		return lines.join('\n');
       
   444 	}
       
   445 	
       
   446 	// This function returns a portions of the string from pos1 to pos2 inclusive
       
   447 	function Copy(string, pos1, pos2)
       
   448 	{
       
   449 		return string.substr(pos1, pos2 - pos1);
       
   450 	}
       
   451 
       
   452 	var pos	= 0;
       
   453 	
       
   454 	this.originalCode = code;
       
   455 	this.code = Chop(Unindent(code));
       
   456 	this.div = document.createElement('DIV');
       
   457 	this.table = document.createElement('TABLE');
       
   458 	this.matches = new Array();
       
   459 
       
   460 	if(this.CssClass != null)
       
   461 		this.table.className = this.CssClass;
       
   462 
       
   463 	// replace tabs with spaces
       
   464 	if(this.tabsToSpaces == true)
       
   465 		this.code = this.ProcessSmartTabs(this.code);
       
   466 
       
   467 	this.table.border = 0;
       
   468 	this.table.cellSpacing = 0;
       
   469 	this.table.cellPadding = 0;
       
   470 
       
   471 	this.ProcessRegexList();	
       
   472 
       
   473 	// if no matches found, add entire code as plain text
       
   474 	if(this.matches.length == 0)
       
   475 	{
       
   476 		this.AddBit(this.code, null);
       
   477 		this.SwitchToTable();
       
   478 		return;
       
   479 	}
       
   480 
       
   481 	// sort the matches
       
   482 	this.matches = this.matches.sort(dp.sh.Highlighter.SortCallback);
       
   483 
       
   484 	// The following loop checks to see if any of the matches are inside
       
   485 	// of other matches. This process would get rid of highligting strings
       
   486 	// inside comments, keywords inside strings and so on.
       
   487 	for(var i = 0; i < this.matches.length; i++)
       
   488 		if(this.IsInside(this.matches[i]))
       
   489 			this.matches[i] = null;
       
   490 
       
   491 	// Finally, go through the final list of matches and pull the all
       
   492 	// together adding everything in between that isn't a match.
       
   493 	for(var i = 0; i < this.matches.length; i++)
       
   494 	{
       
   495 		var match = this.matches[i];
       
   496 
       
   497 		if(match == null || match.length == 0)
       
   498 			continue;
       
   499 		
       
   500 		this.AddBit(Copy(this.code, pos, match.index), null);
       
   501 		this.AddBit(match.value, match.css);
       
   502 		
       
   503 		pos = match.index + match.length;
       
   504 	}
       
   505 	
       
   506 	this.AddBit(this.code.substr(pos), null);
       
   507 
       
   508 	this.SwitchToTable();
       
   509 }
       
   510 
       
   511 dp.sh.Highlighter.prototype.GetKeywords = function(str) 
       
   512 {
       
   513 	return '\\b' + str.replace(/ /g, '\\b|\\b') + '\\b';
       
   514 }
       
   515 
       
   516 // highlightes all elements identified by name and gets source code from specified property
       
   517 dp.sh.HighlightAll = function(name, showGutter /* optional */, showControls /* optional */, collapseAll /* optional */, firstLine /* optional */)
       
   518 {
       
   519 	function FindValue()
       
   520 	{
       
   521 		var a = arguments;
       
   522 		
       
   523 		for(var i = 0; i < a.length; i++)
       
   524 		{
       
   525 			if(a[i] == null)
       
   526 				continue;
       
   527 				
       
   528 			if(typeof(a[i]) == 'string' && a[i] != '')
       
   529 				return a[i] + '';
       
   530 		
       
   531 			if(typeof(a[i]) == 'object' && a[i].value != '')
       
   532 				return a[i].value + '';
       
   533 		}
       
   534 		
       
   535 		return null;
       
   536 	}
       
   537 	
       
   538 	function IsOptionSet(value, list)
       
   539 	{
       
   540 		for(var i = 0; i < list.length; i++)
       
   541 			if(list[i] == value)
       
   542 				return true;
       
   543 		
       
   544 		return false;
       
   545 	}
       
   546 	
       
   547 	function GetOptionValue(name, list, defaultValue)
       
   548 	{
       
   549 		var regex = new RegExp('^' + name + '\\[(\\w+)\\]$', 'gi');
       
   550 		var matches = null;
       
   551 
       
   552 		for(var i = 0; i < list.length; i++)
       
   553 			if((matches = regex.exec(list[i])) != null)
       
   554 				return matches[1];
       
   555 		
       
   556 		return defaultValue;
       
   557 	}
       
   558 
       
   559 	var elements = document.getElementsByName(name);
       
   560 	var highlighter = null;
       
   561 	var registered = new Object();
       
   562 	var propertyName = 'value';
       
   563 	
       
   564 	// if no code blocks found, leave
       
   565 	if(elements == null)
       
   566 		return;
       
   567 
       
   568 	// register all brushes
       
   569 	for(var brush in dp.sh.Brushes)
       
   570 	{
       
   571 		var aliases = dp.sh.Brushes[brush].Aliases;
       
   572 		
       
   573 		if(aliases == null)
       
   574 			continue;
       
   575 		
       
   576 		for(var i = 0; i < aliases.length; i++)
       
   577 			registered[aliases[i]] = brush;
       
   578 	}
       
   579 
       
   580 	for(var i = 0; i < elements.length; i++)
       
   581 	{
       
   582 		var element = elements[i];
       
   583 		var options = FindValue(
       
   584 				element.attributes['class'], element.className, 
       
   585 				element.attributes['language'], element.language
       
   586 				);
       
   587 		var language = '';
       
   588 		
       
   589 		if(options == null)
       
   590 			continue;
       
   591 		
       
   592 		options = options.split(':');
       
   593 		
       
   594 		language = options[0].toLowerCase();
       
   595 		
       
   596 		if(registered[language] == null)
       
   597 			continue;
       
   598 		
       
   599 		// instantiate a brush
       
   600 		highlighter = new dp.sh.Brushes[registered[language]]();
       
   601 		
       
   602 		// hide the original element
       
   603 		element.style.display = 'none';
       
   604 
       
   605 		highlighter.addGutter = (showGutter == null) ? !IsOptionSet('nogutter', options) : showGutter;
       
   606 		highlighter.addControls = (showControls == null) ? !IsOptionSet('nocontrols', options) : showControls;
       
   607 		highlighter.collapse = (collapseAll == null) ? IsOptionSet('collapse', options) : collapseAll;
       
   608 		
       
   609 		// first line idea comes from Andrew Collington, thanks!
       
   610 		highlighter.firstLine = (firstLine == null) ? parseInt(GetOptionValue('firstline', options, 1)) : firstLine;
       
   611 
       
   612 		highlighter.Highlight(element[propertyName]);
       
   613 
       
   614 		// place the result table inside a div
       
   615 		var div = document.createElement('DIV');
       
   616 		
       
   617 		div.className = 'dp-highlighter';
       
   618 		div.appendChild(highlighter.table);
       
   619 
       
   620 		element.parentNode.insertBefore(div, element);		
       
   621 	}	
       
   622 }
       
   623 
       
   624 
       
   625 dp.sh.Brushes.Xml = function()
       
   626 {
       
   627 	this.CssClass = 'dp-xml';
       
   628 }
       
   629 
       
   630 dp.sh.Brushes.Xml.prototype	= new dp.sh.Highlighter();
       
   631 dp.sh.Brushes.Xml.Aliases	= ['xml', 'xhtml', 'xslt', 'html', 'xhtml'];
       
   632 
       
   633 dp.sh.Brushes.Xml.prototype.ProcessRegexList = function()
       
   634 {
       
   635 	function push(array, value)
       
   636 	{
       
   637 		array[array.length] = value;
       
   638 	}
       
   639 	
       
   640 	/* If only there was a way to get index of a group within a match, the whole XML
       
   641 	   could be matched with the expression looking something like that:
       
   642 	
       
   643 	   (<!\[CDATA\[\s*.*\s*\]\]>)
       
   644 	   | (<!--\s*.*\s*?-->)
       
   645 	   | (<)*(\w+)*\s*(\w+)\s*=\s*(".*?"|'.*?'|\w+)(/*>)*
       
   646 	   | (</?)(.*?)(/?>)
       
   647 	*/
       
   648 	var index	= 0;
       
   649 	var match	= null;
       
   650 	var regex	= null;
       
   651 
       
   652 	// Match CDATA in the following format <![ ... [ ... ]]>
       
   653 	// <\!\[[\w\s]*?\[(.|\s)*?\]\]>
       
   654 	this.GetMatches(new RegExp('<\\!\\[[\\w\\s]*?\\[(.|\\s)*?\\]\\]>', 'gm'), 'cdata');
       
   655 	
       
   656 	// Match comments
       
   657 	// <!--\s*.*\s*?-->
       
   658 	this.GetMatches(new RegExp('<!--\\s*.*\\s*?-->', 'gm'), 'comments');
       
   659 
       
   660 	// Match attributes and their values
       
   661 	// (\w+)\s*=\s*(".*?"|\'.*?\'|\w+)*
       
   662 	regex = new RegExp('([\\w-\.]+)\\s*=\\s*(".*?"|\'.*?\'|\\w+)*', 'gm');
       
   663 	while((match = regex.exec(this.code)) != null)
       
   664 	{
       
   665 		push(this.matches, new dp.sh.Match(match[1], match.index, 'attribute'));
       
   666 	
       
   667 		// if xml is invalid and attribute has no property value, ignore it	
       
   668 		if(match[2] != undefined)
       
   669 		{
       
   670 			push(this.matches, new dp.sh.Match(match[2], match.index + match[0].indexOf(match[2]), 'attribute-value'));
       
   671 		}
       
   672 	}
       
   673 
       
   674 	// Match opening and closing tag brackets
       
   675 	// </*\?*(?!\!)|/*\?*>
       
   676 	this.GetMatches(new RegExp('</*\\?*(?!\\!)|/*\\?*>', 'gm'), 'tag');
       
   677 
       
   678 	// Match tag names
       
   679 	// </*\?*\s*(\w+)
       
   680 	regex = new RegExp('</*\\?*\\s*([\\w-\.]+)', 'gm');
       
   681 	while((match = regex.exec(this.code)) != null)
       
   682 	{
       
   683 		push(this.matches, new dp.sh.Match(match[1], match.index + match[0].indexOf(match[1]), 'tag-name'));
       
   684 	}
       
   685 }
       
   686 
       
   687 
       
   688 dp.sh.Brushes.Php = function()
       
   689 {
       
   690 	var keywords =	'and or xor __FILE__ __LINE__ array as break case ' +
       
   691 					'cfunction class const continue declare default die do echo else ' +
       
   692 					'elseif empty enddeclare endfor endforeach endif endswitch endwhile eval exit ' +
       
   693 					'extends for foreach function global if include include_once isset list ' +
       
   694 					'new old_function print require require_once return static switch unset use ' +
       
   695 					'var while __FUNCTION__ __CLASS__';
       
   696 
       
   697 	this.regexList = [
       
   698 		{ regex: new RegExp('//.*$', 'gm'),							css: 'comment' },			// one line comments
       
   699 		{ regex: new RegExp('/\\*[\\s\\S]*?\\*/', 'g'),				css: 'comment' },			// multiline comments
       
   700 		{ regex: new RegExp('"(?:[^"\n]|[\"])*?"', 'g'),			css: 'string' },			// double quoted strings
       
   701 		{ regex: new RegExp("'(?:[^'\n]|[\'])*?'", 'g'),			css: 'string' },			// single quoted strings
       
   702 		{ regex: new RegExp('\\$\\w+', 'g'),						css: 'vars' },				// variables
       
   703 		{ regex: new RegExp(this.GetKeywords(keywords), 'gm'),		css: 'keyword' }			// keyword
       
   704 		];
       
   705 
       
   706 	this.CssClass = 'dp-c';
       
   707 }
       
   708 
       
   709 dp.sh.Brushes.Php.prototype	= new dp.sh.Highlighter();
       
   710 dp.sh.Brushes.Php.Aliases	= ['php'];
       
   711 
       
   712 
       
   713 dp.sh.Brushes.JScript = function()
       
   714 {
       
   715 	var keywords =	'abstract boolean break byte case catch char class const continue debugger ' +
       
   716 					'default delete do double else enum export extends false final finally float ' +
       
   717 					'for function goto if implements import in instanceof int interface long native ' +
       
   718 					'new null package private protected public return short static super switch ' +
       
   719 					'synchronized this throw throws transient true try typeof var void volatile while with';
       
   720 
       
   721 	this.regexList = [
       
   722 		{ regex: new RegExp('//.*$', 'gm'),							css: 'comment' },			// one line comments
       
   723 		{ regex: new RegExp('/\\*[\\s\\S]*?\\*/', 'g'),				css: 'comment' },			// multiline comments
       
   724 		{ regex: new RegExp('"(?:[^"\n]|[\"])*?"', 'g'),			css: 'string' },			// double quoted strings
       
   725 		{ regex: new RegExp("'(?:[^'\n]|[\'])*?'", 'g'),			css: 'string' },			// single quoted strings
       
   726 		{ regex: new RegExp('^\\s*#.*', 'gm'),						css: 'preprocessor' },		// preprocessor tags like #region and #endregion
       
   727 		{ regex: new RegExp(this.GetKeywords(keywords), 'gm'),		css: 'keyword' }			// keywords
       
   728 		];
       
   729 
       
   730 	this.CssClass = 'dp-c';
       
   731 }
       
   732 
       
   733 dp.sh.Brushes.JScript.prototype	= new dp.sh.Highlighter();
       
   734 dp.sh.Brushes.JScript.Aliases	= ['js', 'jscript', 'javascript'];
       
   735 
       
   736 dp.sh.Brushes.CSS = function() {
       
   737     //Not used yet - added to values
       
   738     var tags = 'abbr acronym address applet area a b base basefont bdo big blockquote body br button ' +
       
   739             'caption center cite code col colgroup dd del dfn dir div dl dt em fieldset form frame frameset h1 h2 h3 h4 h5 h6 head hr html img i ' +
       
   740             'iframe img input ins isindex kbd label legend li link map menu meta noframes noscript ol optgroup option p param pre q s samp script select ' +
       
   741             'span strike strong style sub sup table tbody td textarea tfoot th thead title tr tt ul u';
       
   742 	var keywords =	'ascent azimuth background-attachment background-color background-image background-position ' +
       
   743 			'background-repeat background baseline bbox border-collapse border-color border-spacing border-style border-top ' +
       
   744 			'border-right border-bottom border-left border-top-color border-right-color border-bottom-color border-left-color ' +
       
   745 			'border-top-style border-right-style border-bottom-style border-left-style border-top-width border-right-width ' +
       
   746 			'border-bottom-width border-left-width border-width border bottom cap-height caption-side centerline clear clip color ' +
       
   747 			'content counter-increment counter-reset cue-after cue-before cue cursor definition-src descent direction display ' +
       
   748 			'elevation empty-cells float font-size-adjust font-family font-size font-stretch font-style font-variant font-weight font ' +
       
   749 			'height letter-spacing line-height list-style-image list-style-position list-style-type list-style margin-top ' +
       
   750 			'margin-right margin-bottom margin-left margin marker-offset marks mathline max-height max-width min-height min-width orphans ' +
       
   751 			'outline-color outline-style outline-width outline overflow-x overflow-y overflow padding-top padding-right padding-bottom padding-left padding page ' +
       
   752 			'page-break-after page-break-before page-break-inside pause pause-after pause-before pitch pitch-range play-during position ' +
       
   753 			'quotes richness right left bottom top size slope src speak-header speak-numeral speak-punctuation speak speech-rate stemh stemv stress ' +
       
   754 			'table-layout text-align text-decoration text-indent text-shadow text-transform unicode-bidi unicode-range units-per-em ' +
       
   755 			'vertical-align visibility voice-family volume white-space widows width widths word-spacing x-height z-index zoom important after filter opacity';
       
   756 
       
   757     var values = 'progid:DXImageTransform.Microsoft.AlphaImageLoader src sizingMethod alpha opacity ' +
       
   758             'above absolute all always aqua armenian attr aural auto avoid baseline behind below bidi-override black blink block blue bold bolder both bottom braille capitalize center center-left center-right circle close-quote code collapse compact condensed '+
       
   759 			'continuous counter counters crop cross crosshair cursive dashed decimal decimal-leading-zero default digits disc dotted double embed embossed e-resize expanded extra-condensed extra-expanded fantasy far-left far-right fast faster fixed format fuchsia '+
       
   760 			'gray green groove handheld hebrew help hidden hide high higher inline-table inline inset inside invert italic justify landscape large larger left-side left leftwards level lighter lime line-through list-item local loud lower-alpha '+
       
   761 			'lowercase lower-greek lower-latin lower-roman lower low ltr marker maroon medium message-box middle mix move narrower navy ne-resize no-close-quote none no-open-quote no-repeat normal nowrap n-resize nw-resize oblique olive once open-quote outset '+
       
   762 			'outside overline pointer portrait print projection purple red relative repeat repeat-x repeat-y rgb ridge right right-side rightwards rtl run-in screen scroll semi-condensed semi-expanded separate se-resize show silent silver slower slow '+
       
   763 			'small small-caps small-caption smaller soft solid speech spell-out square s-resize static status-bar sub super sw-resize table-caption table-cell table-column table-column-group table-footer-group table-header-group table-row table-row-group teal '+
       
   764 			'text-bottom text-top thick thin top transparent tty tv ultra-condensed ultra-expanded underline upper-alpha uppercase upper-latin upper-roman url visible wait white wider w-resize x-fast x-high x-large x-loud x-low x-slow x-small x-soft xx-large xx-small yellow';
       
   765 	
       
   766 
       
   767 	this.regexList = [
       
   768 		{ regex: new RegExp('//.*$', 'gm'),							css: 'comment' },			// one line comments
       
   769 		{ regex: new RegExp('/\\*[\\s\\S]*?\\*/', 'g'),				css: 'comment' },			// multiline comments
       
   770 		{ regex: new RegExp('"(?:[^"\n]|[\"])*?"', 'g'),			css: 'string' },			// double quoted strings
       
   771 		{ regex: new RegExp("'(?:[^'\n]|[\'])*?'", 'g'),			css: 'string' },			// single quoted strings
       
   772 		{ regex: new RegExp('^\\s*.*{', 'gm'),						css: 'preprocessor' },		// everything before a {
       
   773 		{ regex: new RegExp('}', 'gm'),						css: 'preprocessor' },		// The }
       
   774 		{ regex: new RegExp(this.GetKeywordsCSS(keywords), 'gm'),		css: 'keyword' },		// keywords
       
   775 		{ regex: new RegExp(this.GetValuesCSS(values), 'gm'),		css: 'value' },			// values
       
   776         { regex: new RegExp('(-?\\d+)(\.\\d+)?(px|em|pt|\:|\%|)', 'g'),  css: 'value' }        //Sizes
       
   777 		];
       
   778         //Not used any more
       
   779         /*
       
   780         { regex: new RegExp('(-?\\d+)(\.\\d+)', 'g'),  css: 'value' },        //Plain Numbers
       
   781         { regex: new RegExp('(0(?=;))', 'g'),  css: 'value' }        //Number 0
       
   782 		{ regex: new RegExp('\([.]\)', 'gm'),			css: 'string' },			// Things in parenthesis
       
   783         { regex: new RegExp('\\#[a-zA-Z0-9]{3,6}', 'g'),            css: 'colors' },            // html colors  
       
   784 		{ regex: new RegExp(this.GetKeywords(tags), 'g'),		css: 'tags' },			// keywords
       
   785         */
       
   786 
       
   787 	this.CssClass = 'dp-css';
       
   788 }
       
   789 dp.sh.Highlighter.prototype.GetKeywordsCSS = function(str) {
       
   790 	//var str = '\\b' + str.replace(/ /g, '(?=:)\\b|\\b') + '\:\\b';
       
   791 	var str = '\\b([a-z_]|)' + str.replace(/ /g, '(?=:)\\b|\\b([a-z_\\*]|\\*|)') + '(?=:)\\b';
       
   792     //console.log(str);
       
   793     return str;
       
   794 }
       
   795 dp.sh.Highlighter.prototype.GetValuesCSS = function(str) {
       
   796 	var str = '\\b' + str.replace(/ /g, '(?!-)(?!:)\\b|\\b()') + '\:\\b';
       
   797     //console.log(str);
       
   798     return str;
       
   799 }
       
   800 
       
   801 dp.sh.Brushes.CSS.prototype	= new dp.sh.Highlighter();
       
   802 dp.sh.Brushes.CSS.Aliases	= ['css'];
       
   803 
       
   804 
       
   805