1 | /** |
---|
2 | * Code Syntax Highlighter. |
---|
3 | * Version 1.2.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 | }, |
---|
29 | Version : '1.2.0' |
---|
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"><div class="para title">dp.SyntaxHighlighter</div><div class="para">Version: {V}</div><div class="para"><a href="http://www.dreamprojections.com/sh/?ref=about" target="_blank">http://www.dreamprojections.com/SyntaxHighlighter</a></div>©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 : '', |
---|
39 | CopyToClipboard : '', |
---|
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, '<'); |
---|
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, '<'); |
---|
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, '&'); |
---|
206 | str = str.replace(/ /g, ' '); |
---|
207 | str = str.replace(/</g, '<'); |
---|
208 | str = str.replace(/\n/gm, ' <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(' <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 | // Safari fix: for some reason lowercase <br> isn't getting picked up, even though 'i' is set |
---|
327 | var lines = this.div.innerHTML.split(/<BR>/gi); |
---|
328 | var row = null; |
---|
329 | var cell = null; |
---|
330 | var tBody = null; |
---|
331 | var html = ''; |
---|
332 | var pipe = ' | '; |
---|
333 | |
---|
334 | // creates an anchor to a utility |
---|
335 | function UtilHref(util, text) |
---|
336 | { |
---|
337 | return '<a href="#" onclick="dp.sh.Utils.' + util + '(this); return false;">' + text + '</a>'; |
---|
338 | } |
---|
339 | |
---|
340 | tBody = document.createElement('TBODY'); // can be created and all others go to tBodies collection. |
---|
341 | |
---|
342 | this.table.appendChild(tBody); |
---|
343 | |
---|
344 | if(this.addGutter == true) |
---|
345 | { |
---|
346 | row = tBody.insertRow(-1); |
---|
347 | cell = row.insertCell(-1); |
---|
348 | cell.className = 'tools-corner'; |
---|
349 | } |
---|
350 | |
---|
351 | if(this.addControls == true) |
---|
352 | { |
---|
353 | var tHead = document.createElement('THEAD'); // controls will be placed in here |
---|
354 | this.table.appendChild(tHead); |
---|
355 | |
---|
356 | row = tHead.insertRow(-1); |
---|
357 | |
---|
358 | // add corner if there's a gutter |
---|
359 | if(this.addGutter == true) |
---|
360 | { |
---|
361 | cell = row.insertCell(-1); |
---|
362 | cell.className = 'tools-corner'; |
---|
363 | } |
---|
364 | |
---|
365 | cell = row.insertCell(-1); |
---|
366 | |
---|
367 | // preserve some variables for the controls |
---|
368 | cell.originalCode = this.originalCode; |
---|
369 | cell.processedCode = this.code; |
---|
370 | cell.className = 'tools'; |
---|
371 | |
---|
372 | if(this.collapse == true) |
---|
373 | { |
---|
374 | tBody.className = 'hide'; |
---|
375 | cell.innerHTML += '<span><b>' + UtilHref('Expand', dp.sh.Strings.ExpandCode) + '</b>' + pipe + '</span>'; |
---|
376 | } |
---|
377 | |
---|
378 | cell.innerHTML += UtilHref('ViewSource', dp.sh.Strings.ViewPlain) ; |
---|
379 | |
---|
380 | // IE has this clipboard object which is easy enough to use |
---|
381 | if(window.clipboardData) |
---|
382 | cell.innerHTML += pipe + UtilHref('ToClipboard', dp.sh.Strings.CopyToClipboard); |
---|
383 | } |
---|
384 | |
---|
385 | for(var i = 0; i < lines.length - 1; i++) |
---|
386 | { |
---|
387 | row = tBody.insertRow(-1); |
---|
388 | |
---|
389 | if(this.addGutter == true) |
---|
390 | { |
---|
391 | cell = row.insertCell(-1); |
---|
392 | cell.className = 'gutter'; |
---|
393 | cell.innerHTML = i + 1; |
---|
394 | } |
---|
395 | |
---|
396 | cell = row.insertCell(-1); |
---|
397 | cell.className = 'line' + (i % 2 + 1); // uses .line1 and .line2 css styles for alternating lines |
---|
398 | cell.innerHTML = lines[i]; |
---|
399 | } |
---|
400 | |
---|
401 | this.div.innerHTML = ''; |
---|
402 | } |
---|
403 | |
---|
404 | dp.sh.Highlighter.prototype.Highlight = function(code) |
---|
405 | { |
---|
406 | function Trim(str) |
---|
407 | { |
---|
408 | return str.replace(/^\s*(.*?)[\s\n]*$/g, '$1'); |
---|
409 | } |
---|
410 | |
---|
411 | function Chop(str) |
---|
412 | { |
---|
413 | return str.replace(/\n*$/, '').replace(/^\n*/, ''); |
---|
414 | } |
---|
415 | |
---|
416 | function Unindent(str) |
---|
417 | { |
---|
418 | var lines = str.split('\n'); |
---|
419 | var indents = new Array(); |
---|
420 | var regex = new RegExp('^\\s*', 'g'); |
---|
421 | var min = 1000; |
---|
422 | |
---|
423 | // go through every line and check for common number of indents |
---|
424 | for(var i = 0; i < lines.length && min > 0; i++) |
---|
425 | { |
---|
426 | if(Trim(lines[i]).length == 0) |
---|
427 | continue; |
---|
428 | |
---|
429 | var matches = regex.exec(lines[i]); |
---|
430 | |
---|
431 | if(matches != null && matches.length > 0) |
---|
432 | min = Math.min(matches[0].length, min); |
---|
433 | } |
---|
434 | |
---|
435 | // trim minimum common number of white space from the begining of every line |
---|
436 | if(min > 0) |
---|
437 | for(var i = 0; i < lines.length; i++) |
---|
438 | lines[i] = lines[i].substr(min); |
---|
439 | |
---|
440 | return lines.join('\n'); |
---|
441 | } |
---|
442 | |
---|
443 | // This function returns a portions of the string from pos1 to pos2 inclusive |
---|
444 | function Copy(string, pos1, pos2) |
---|
445 | { |
---|
446 | return string.substr(pos1, pos2 - pos1); |
---|
447 | } |
---|
448 | |
---|
449 | var pos = 0; |
---|
450 | |
---|
451 | this.originalCode = code; |
---|
452 | this.code = Chop(Unindent(code)); |
---|
453 | this.div = document.createElement('DIV'); |
---|
454 | this.table = document.createElement('TABLE'); |
---|
455 | this.matches = new Array(); |
---|
456 | |
---|
457 | if(this.CssClass != null) |
---|
458 | this.table.className = this.CssClass; |
---|
459 | |
---|
460 | // replace tabs with spaces |
---|
461 | if(this.tabsToSpaces == true) |
---|
462 | this.code = this.ProcessSmartTabs(this.code); |
---|
463 | |
---|
464 | this.table.border = 0; |
---|
465 | this.table.cellSpacing = 0; |
---|
466 | this.table.cellPadding = 0; |
---|
467 | |
---|
468 | this.ProcessRegexList(); |
---|
469 | |
---|
470 | // if no matches found, add entire code as plain text |
---|
471 | if(this.matches.length == 0) |
---|
472 | { |
---|
473 | this.AddBit(this.code, null); |
---|
474 | this.SwitchToTable(); |
---|
475 | return; |
---|
476 | } |
---|
477 | |
---|
478 | // sort the matches |
---|
479 | this.matches = this.matches.sort(dp.sh.Highlighter.SortCallback); |
---|
480 | |
---|
481 | // The following loop checks to see if any of the matches are inside |
---|
482 | // of other matches. This process would get rid of highligting strings |
---|
483 | // inside comments, keywords inside strings and so on. |
---|
484 | for(var i = 0; i < this.matches.length; i++) |
---|
485 | if(this.IsInside(this.matches[i])) |
---|
486 | this.matches[i] = null; |
---|
487 | |
---|
488 | // Finally, go through the final list of matches and pull the all |
---|
489 | // together adding everything in between that isn't a match. |
---|
490 | for(var i = 0; i < this.matches.length; i++) |
---|
491 | { |
---|
492 | var match = this.matches[i]; |
---|
493 | |
---|
494 | if(match == null || match.length == 0) |
---|
495 | continue; |
---|
496 | |
---|
497 | this.AddBit(Copy(this.code, pos, match.index), null); |
---|
498 | this.AddBit(match.value, match.css); |
---|
499 | |
---|
500 | pos = match.index + match.length; |
---|
501 | } |
---|
502 | |
---|
503 | this.AddBit(this.code.substr(pos), null); |
---|
504 | |
---|
505 | this.SwitchToTable(); |
---|
506 | } |
---|
507 | |
---|
508 | dp.sh.Highlighter.prototype.GetKeywords = function(str) |
---|
509 | { |
---|
510 | return '\\b' + str.replace(/ /g, '\\b|\\b') + '\\b'; |
---|
511 | } |
---|
512 | |
---|
513 | // highlightes all elements identified by name and gets source code from specified property |
---|
514 | dp.sh.HighlightAll = function(name, showGutter /* optional */, showControls /* optional */, collapseAll /* optional */) |
---|
515 | { |
---|
516 | function FindValue() |
---|
517 | { |
---|
518 | var a = arguments; |
---|
519 | |
---|
520 | for(var i = 0; i < a.length; i++) |
---|
521 | { |
---|
522 | if(a[i] == null) |
---|
523 | continue; |
---|
524 | |
---|
525 | if(typeof(a[i]) == 'string' && a[i] != '') |
---|
526 | return a[i] + ''; |
---|
527 | |
---|
528 | if(typeof(a[i]) == 'object' && a[i].value != '') |
---|
529 | return a[i].value + ''; |
---|
530 | } |
---|
531 | |
---|
532 | return null; |
---|
533 | } |
---|
534 | |
---|
535 | function IsOptionSet(value, list) |
---|
536 | { |
---|
537 | for(var i = 0; i < list.length; i++) |
---|
538 | if(list[i] == value) |
---|
539 | return true; |
---|
540 | |
---|
541 | return false; |
---|
542 | } |
---|
543 | |
---|
544 | var elements = document.getElementsByName(name); |
---|
545 | var highlighter = null; |
---|
546 | var registered = new Object(); |
---|
547 | var propertyName = 'value'; |
---|
548 | |
---|
549 | // if no code blocks found, leave |
---|
550 | if(elements == null) |
---|
551 | return; |
---|
552 | |
---|
553 | // register all brushes |
---|
554 | for(var brush in dp.sh.Brushes) |
---|
555 | { |
---|
556 | var aliases = dp.sh.Brushes[brush].Aliases; |
---|
557 | |
---|
558 | if(aliases == null) |
---|
559 | continue; |
---|
560 | |
---|
561 | for(var i = 0; i < aliases.length; i++) |
---|
562 | registered[aliases[i]] = brush; |
---|
563 | } |
---|
564 | |
---|
565 | for(var i = 0; i < elements.length; i++) |
---|
566 | { |
---|
567 | var element = elements[i]; |
---|
568 | var options = FindValue( |
---|
569 | element.attributes['class'], element.className, |
---|
570 | element.attributes['language'], element.language |
---|
571 | ); |
---|
572 | var language = ''; |
---|
573 | |
---|
574 | if(options == null) |
---|
575 | continue; |
---|
576 | |
---|
577 | options = options.split(':'); |
---|
578 | |
---|
579 | language = options[0].toLowerCase(); |
---|
580 | |
---|
581 | if(registered[language] == null) |
---|
582 | continue; |
---|
583 | |
---|
584 | // instantiate a brush |
---|
585 | highlighter = new dp.sh.Brushes[registered[language]](); |
---|
586 | |
---|
587 | // hide the original element |
---|
588 | element.style.display = 'none'; |
---|
589 | |
---|
590 | highlighter.addGutter = (showGutter == null) ? !IsOptionSet('nogutter', options) : showGutter; |
---|
591 | highlighter.addControls = (showControls == null) ? !IsOptionSet('nocontrols', options) : showControls; |
---|
592 | highlighter.collapse = (collapseAll == null) ? IsOptionSet('collapse', options) : collapseAll; |
---|
593 | |
---|
594 | highlighter.Highlight(element[propertyName]); |
---|
595 | |
---|
596 | // place the result table inside a div |
---|
597 | var div = document.createElement('DIV'); |
---|
598 | |
---|
599 | div.className = 'dp-highlighter'; |
---|
600 | div.appendChild(highlighter.table); |
---|
601 | |
---|
602 | element.parentNode.insertBefore(div, element); |
---|
603 | } |
---|
604 | } |
---|
605 | |
---|
606 | |
---|
607 | dp.sh.Brushes.JScript = function() |
---|
608 | { |
---|
609 | var keywords = 'abstract boolean break byte case catch char class const continue debugger ' + |
---|
610 | 'default delete do double else enum export extends false final finally float ' + |
---|
611 | 'for function goto if implements import in instanceof int interface long native ' + |
---|
612 | 'new null package private protected public return short static super switch ' + |
---|
613 | 'synchronized this throw throws transient true try typeof var void volatile while with'; |
---|
614 | |
---|
615 | this.regexList = [ |
---|
616 | { regex: new RegExp('//.*$', 'gm'), css: 'comment' }, // one line comments |
---|
617 | { regex: new RegExp('/\\*[\\s\\S]*?\\*/', 'g'), css: 'comment' }, // multiline comments |
---|
618 | { regex: new RegExp('"(?:[^"\n]|[\"])*"', 'g'), css: 'string' }, // double quoted strings |
---|
619 | { regex: new RegExp("'(?:[^'\n]|[\'])*'", 'g'), css: 'string' }, // single quoted strings |
---|
620 | { regex: new RegExp('^\\s*#.*', 'gm'), css: 'preprocessor' }, // preprocessor tags like #region and #endregion |
---|
621 | { regex: new RegExp(this.GetKeywords(keywords), 'gm'), css: 'keyword' } // keywords |
---|
622 | ]; |
---|
623 | |
---|
624 | this.CssClass = 'dp-c'; |
---|
625 | } |
---|
626 | |
---|
627 | dp.sh.Brushes.JScript.prototype = new dp.sh.Highlighter(); |
---|
628 | dp.sh.Brushes.JScript.Aliases = ['js', 'jscript', 'javascript']; |
---|
629 | |
---|
630 | |
---|
631 | dp.sh.Brushes.Php = function() |
---|
632 | { |
---|
633 | var keywords = 'and or xor __FILE__ __LINE__ array as break case ' + |
---|
634 | 'cfunction class const continue declare default die do echo else ' + |
---|
635 | 'elseif empty enddeclare endfor endforeach endif endswitch endwhile eval exit ' + |
---|
636 | 'extends for foreach function global if include include_once isset list ' + |
---|
637 | 'new old_function print require require_once return static switch unset use ' + |
---|
638 | 'var while __FUNCTION__ __CLASS__'; |
---|
639 | |
---|
640 | this.regexList = [ |
---|
641 | { regex: new RegExp('//.*$', 'gm'), css: 'comment' }, // one line comments |
---|
642 | { regex: new RegExp('/\\*[\\s\\S]*?\\*/', 'g'), css: 'comment' }, // multiline comments |
---|
643 | { regex: new RegExp('"(?:[^"\n]|[\"])*"', 'g'), css: 'string' }, // double quoted strings |
---|
644 | { regex: new RegExp("'(?:[^'\n]|[\'])*'", 'g'), css: 'string' }, // single quoted strings |
---|
645 | { regex: new RegExp('\\$\\w+', 'g'), css: 'vars' }, // variables |
---|
646 | { regex: new RegExp(this.GetKeywords(keywords), 'gm'), css: 'keyword' } // keyword |
---|
647 | ]; |
---|
648 | |
---|
649 | this.CssClass = 'dp-c'; |
---|
650 | } |
---|
651 | |
---|
652 | dp.sh.Brushes.Php.prototype = new dp.sh.Highlighter(); |
---|
653 | dp.sh.Brushes.Php.Aliases = ['php']; |
---|
654 | |
---|
655 | |
---|
656 | |
---|
657 | dp.sh.Brushes.Xml = function() |
---|
658 | { |
---|
659 | this.CssClass = 'dp-xml'; |
---|
660 | } |
---|
661 | |
---|
662 | dp.sh.Brushes.Xml.prototype = new dp.sh.Highlighter(); |
---|
663 | dp.sh.Brushes.Xml.Aliases = ['xml', 'xhtml', 'xslt', 'html', 'xhtml']; |
---|
664 | |
---|
665 | dp.sh.Brushes.Xml.prototype.ProcessRegexList = function() |
---|
666 | { |
---|
667 | function push(array, value) |
---|
668 | { |
---|
669 | array[array.length] = value; |
---|
670 | } |
---|
671 | |
---|
672 | /* If only there was a way to get index of a group within a match, the whole XML |
---|
673 | could be matched with the expression looking something like that: |
---|
674 | |
---|
675 | (<!\[CDATA\[\s*.*\s*\]\]>) |
---|
676 | | (<!--\s*.*\s*?-->) |
---|
677 | | (<)*(\w+)*\s*(\w+)\s*=\s*(".*?"|'.*?'|\w+)(/*>)* |
---|
678 | | (</?)(.*?)(/?>) |
---|
679 | */ |
---|
680 | var index = 0; |
---|
681 | var match = null; |
---|
682 | var regex = null; |
---|
683 | |
---|
684 | // Match CDATA in the following format <![ ... [ ... ]]> |
---|
685 | // <\!\[[\w\s]*?\[(.|\s)*?\]\]> |
---|
686 | this.GetMatches(new RegExp('<\\!\\[[\\w\\s]*?\\[(.|\\s)*?\\]\\]>', 'gm'), 'cdata'); |
---|
687 | |
---|
688 | // Match comments |
---|
689 | // <!--\s*.*\s*?--> |
---|
690 | this.GetMatches(new RegExp('<!--\\s*.*\\s*?-->', 'gm'), 'comments'); |
---|
691 | |
---|
692 | // Match attributes and their values |
---|
693 | // (\w+)\s*=\s*(".*?"|\'.*?\'|\w+)* |
---|
694 | regex = new RegExp('([\\w-\.]+)\\s*=\\s*(".*?"|\'.*?\'|\\w+)*', 'gm'); |
---|
695 | while((match = regex.exec(this.code)) != null) |
---|
696 | { |
---|
697 | push(this.matches, new dp.sh.Match(match[1], match.index, 'attribute')); |
---|
698 | |
---|
699 | // if xml is invalid and attribute has no property value, ignore it |
---|
700 | if(match[2] != undefined) |
---|
701 | { |
---|
702 | push(this.matches, new dp.sh.Match(match[2], match.index + match[0].indexOf(match[2]), 'attribute-value')); |
---|
703 | } |
---|
704 | } |
---|
705 | |
---|
706 | // Match opening and closing tag brackets |
---|
707 | // </*\?*(?!\!)|/*\?*> |
---|
708 | this.GetMatches(new RegExp('</*\\?*(?!\\!)|/*\\?*>', 'gm'), 'tag'); |
---|
709 | |
---|
710 | // Match tag names |
---|
711 | // </*\?*\s*(\w+) |
---|
712 | regex = new RegExp('</*\\?*\\s*([\\w-\.]+)', 'gm'); |
---|
713 | while((match = regex.exec(this.code)) != null) |
---|
714 | { |
---|
715 | push(this.matches, new dp.sh.Match(match[1], match.index + match[0].indexOf(match[1]), 'tag-name')); |
---|
716 | } |
---|
717 | } |
---|
718 | |
---|
719 | |
---|
720 | dp.sh.Brushes.CSS = function() |
---|
721 | { |
---|
722 | var keywords = 'link over active visited'; |
---|
723 | |
---|
724 | this.regexList = [ |
---|
725 | { regex: new RegExp('/\\*[\\s\\S]*?\\*/', 'g'), css: 'comment' }, // multiline comments |
---|
726 | { regex: new RegExp('"(?:[^"\n]|[\"])*"', 'g'), css: 'string' }, // double quoted strings |
---|
727 | { regex: new RegExp("'(?:[^'\n]|[\'])*'", 'g'), css: 'string' }, // single quoted strings |
---|
728 | { regex: new RegExp('^\\s*#.*', 'gm'), css: 'preprocessor' }, // preprocessor tags like #region and #endregion |
---|
729 | { regex: new RegExp(this.GetKeywords(keywords), 'gm'), css: 'keyword' } // keywords |
---|
730 | ]; |
---|
731 | |
---|
732 | this.CssClass = 'dp-c'; |
---|
733 | } |
---|
734 | |
---|
735 | dp.sh.Brushes.CSS.prototype = new dp.sh.Highlighter(); |
---|
736 | dp.sh.Brushes.CSS.Aliases = ['css']; |
---|