/* Syntax highlighting with language autodetection. http://softwaremaniacs.org/soft/highlight/ */ var hljs = new function() { var LANGUAGES = {}; var selected_languages = {}; function escape(value) { return value.replace(/&/gm, '&').replace(//gm, '>'); }; function contains(array, item) { if (!array) return false; for (var i = 0; i < array.length; i++) if (array[i] == item) return true; return false; }; function langRe(language, value, global) { var mode = 'm' + (language.case_insensitive ? 'i' : '') + (global ? 'g' : ''); return new RegExp(value, mode); }; function findCode(pre) { var node; for (var i = 0; i < pre.childNodes.length; i++) { node = pre.childNodes[i]; if (node.nodeName == 'CODE') return node; if (!(node.nodeType == 3 && node.nodeValue.match(/\s+/))) return null; }; }; function blockText(block) { var result = ''; for (var i = 0; i < block.childNodes.length; i++) if (block.childNodes[i].nodeType == 3) result += block.childNodes[i].nodeValue; else if (block.childNodes[i].nodeName == 'BR') result += '\n'; else result += blockText(block.childNodes[i]); return result; }; function blockLanguage(block) { var classes = block.className.split(/\s+/); classes = classes.concat(block.parentNode.className.split(/\s+/)); for (var i = 0; i < classes.length; i++) { var class_ = classes[i].replace(/^language-/, ''); if (class_ == 'no-highlight') { throw 'No highlight' }; if (LANGUAGES[class_]) { return class_; }; }; }; function nodeStream(node) { var result = []; (function (node, offset) { for (var i = 0; i < node.childNodes.length; i++) { if (node.childNodes[i].nodeType == 3) offset += node.childNodes[i].nodeValue.length; else if (node.childNodes[i].nodeName == 'BR') offset += 1; else { result.push({ event: 'start', offset: offset, node: node.childNodes[i] }); offset = arguments.callee(node.childNodes[i], offset); result.push({ event: 'stop', offset: offset, node: node.childNodes[i] }); }; }; return offset; })(node, 0); return result; }; function mergeStreams(stream1, stream2, value) { var processed = 0; var result = ''; var nodeStack = []; function selectStream() { if (stream1.length && stream2.length) { if (stream1[0].offset != stream2[0].offset) return (stream1[0].offset < stream2[0].offset) ? stream1 : stream2; else return (stream1[0].event == 'start' && stream2[0].event == 'stop') ? stream2 : stream1; } else { return stream1.length ? stream1 : stream2; }; }; function open(node) { var result = '<' + node.nodeName.toLowerCase(); for (var i = 0; i < node.attributes.length; i++) { var attribute = node.attributes[i]; result += ' ' + attribute.nodeName.toLowerCase(); if (attribute.nodeValue != undefined) { result += '="' + escape(attribute.nodeValue) + '"'; }; }; return result + '>'; }; function close(node) { return '' + node.nodeName.toLowerCase() + '>'; }; while (stream1.length || stream2.length) { var current = selectStream().splice(0, 1)[0]; result += escape(value.substr(processed, current.offset - processed)); processed = current.offset; if ( current.event == 'start') { result += open(current.node); nodeStack.push(current.node); } else if (current.event == 'stop') { var i = nodeStack.length; do { i--; var node = nodeStack[i]; result += close(node); } while (node != current.node); nodeStack.splice(i, 1); while (i < nodeStack.length) { result += open(nodeStack[i]); i++; }; }; }; result += value.substr(processed); return result; }; function highlight(language_name, value) { function compileSubModes(mode, language) { mode.sub_modes = []; for (var i = 0; i < mode.contains.length; i++) { for (var j = 0; j < language.modes.length; j++) { if (language.modes[j].className == mode.contains[i]) { mode.sub_modes[mode.sub_modes.length] = language.modes[j]; }; }; }; }; function subMode(lexem, mode) { if (!mode.contains) { return null; }; if (!mode.sub_modes) { compileSubModes(mode, language); }; for (var i = 0; i < mode.sub_modes.length; i++) { if (mode.sub_modes[i].beginRe.test(lexem)) { return mode.sub_modes[i]; }; }; return null; }; function endOfMode(mode_index, lexem) { if (modes[mode_index].end && modes[mode_index].endRe.test(lexem)) return 1; if (modes[mode_index].endsWithParent) { var level = endOfMode(mode_index - 1, lexem); return level ? level + 1 : 0; }; return 0; }; function isIllegal(lexem, mode) { return mode.illegalRe && mode.illegalRe.test(lexem); }; function compileTerminators(mode, language) { var terminators = []; function addTerminator(re) { if (!contains(terminators, re)) { terminators[terminators.length] = re; }; }; if (mode.contains) for (var i = 0; i < language.modes.length; i++) { if (contains(mode.contains, language.modes[i].className)) { addTerminator(language.modes[i].begin); }; }; var index = modes.length - 1; do { if (modes[index].end) { addTerminator(modes[index].end); }; index--; } while (modes[index + 1].endsWithParent); if (mode.illegal) { addTerminator(mode.illegal); }; var terminator_re = '(' + terminators[0]; for (var i = 0; i < terminators.length; i++) terminator_re += '|' + terminators[i]; terminator_re += ')'; return langRe(language, terminator_re); }; function eatModeChunk(value, index) { var mode = modes[modes.length - 1]; if (!mode.terminators) { mode.terminators = compileTerminators(mode, language); }; value = value.substr(index); var match = mode.terminators.exec(value); if (!match) return [value, '', true]; if (match.index == 0) return ['', match[0], false]; else return [value.substr(0, match.index), match[0], false]; }; function keywordMatch(mode, match) { var match_str = language.case_insensitive ? match[0].toLowerCase() : match[0]; for (var className in mode.keywordGroups) { if (!mode.keywordGroups.hasOwnProperty(className)) continue; var value = mode.keywordGroups[className].hasOwnProperty(match_str); if (value) return [className, value]; }; return false; }; function processKeywords(buffer, mode) { if (!mode.keywords || !mode.lexems) return escape(buffer); if (!mode.lexemsRe) { var lexems_re = '(' + mode.lexems[0]; for (var i = 1; i < mode.lexems.length; i++) lexems_re += '|' + mode.lexems[i]; lexems_re += ')'; mode.lexemsRe = langRe(language, lexems_re, true); }; var result = ''; var last_index = 0; mode.lexemsRe.lastIndex = 0; var match = mode.lexemsRe.exec(buffer); while (match) { result += escape(buffer.substr(last_index, match.index - last_index)); var keyword_match = keywordMatch(mode, match); if (keyword_match) { keyword_count += keyword_match[1]; result += '' + escape(match[0]) + ''; } else { result += escape(match[0]); }; last_index = mode.lexemsRe.lastIndex; match = mode.lexemsRe.exec(buffer); }; result += escape(buffer.substr(last_index, buffer.length - last_index)); return result; }; function processBuffer(buffer, mode) { if (mode.subLanguage && selected_languages[mode.subLanguage]) { var result = highlight(mode.subLanguage, buffer); keyword_count += result.keyword_count; relevance += result.relevance; return result.value; } else { return processKeywords(buffer, mode); }; }; function startNewMode(mode, lexem) { var markup = mode.noMarkup?'':''; if (mode.returnBegin) { result += markup; mode.buffer = ''; } else if (mode.excludeBegin) { result += escape(lexem) + markup; mode.buffer = ''; } else { result += markup; mode.buffer = lexem; }; modes[modes.length] = mode; }; function processModeInfo(buffer, lexem, end) { var current_mode = modes[modes.length - 1]; if (end) { result += processBuffer(current_mode.buffer + buffer, current_mode); return false; }; var new_mode = subMode(lexem, current_mode); if (new_mode) { result += processBuffer(current_mode.buffer + buffer, current_mode); startNewMode(new_mode, lexem); relevance += new_mode.relevance; return new_mode.returnBegin; }; var end_level = endOfMode(modes.length - 1, lexem); if (end_level) { var markup = current_mode.noMarkup?'':''; if (current_mode.returnEnd) { result += processBuffer(current_mode.buffer + buffer, current_mode) + markup; } else if (current_mode.excludeEnd) { result += processBuffer(current_mode.buffer + buffer, current_mode) + markup + escape(lexem); } else { result += processBuffer(current_mode.buffer + buffer + lexem, current_mode) + markup; }; while (end_level > 1) { markup = modes[modes.length - 2].noMarkup?'':''; result += markup; end_level--; modes.length--; }; modes.length--; modes[modes.length - 1].buffer = ''; if (current_mode.starts) { for (var i = 0; i < language.modes.length; i++) { if (language.modes[i].className == current_mode.starts) { startNewMode(language.modes[i], ''); break; }; }; }; return current_mode.returnEnd; }; if (isIllegal(lexem, current_mode)) throw 'Illegal'; }; var language = LANGUAGES[language_name]; var modes = [language.defaultMode]; var relevance = 0; var keyword_count = 0; var result = ''; try { var index = 0; language.defaultMode.buffer = ''; do { var mode_info = eatModeChunk(value, index); var return_lexem = processModeInfo(mode_info[0], mode_info[1], mode_info[2]); index += mode_info[0].length; if (!return_lexem) { index += mode_info[1].length; }; } while (!mode_info[2]); if(modes.length > 1) throw 'Illegal'; return { relevance: relevance, keyword_count: keyword_count, value: result }; } catch (e) { if (e == 'Illegal') { return { relevance: 0, keyword_count: 0, value: escape(value) }; } else { throw e; }; }; }; function compileModes() { for (var i in LANGUAGES) { if (!LANGUAGES.hasOwnProperty(i)) continue; var language = LANGUAGES[i]; for (var j = 0; j < language.modes.length; j++) { var mode = language.modes[j]; if (mode.begin) mode.beginRe = langRe(language, '^' + mode.begin); if (mode.end) mode.endRe = langRe(language, '^' + mode.end); if (mode.illegal) mode.illegalRe = langRe(language, '^(?:' + mode.illegal + ')'); language.defaultMode.illegalRe = langRe(language, '^(?:' + language.defaultMode.illegal + ')'); if (mode.relevance == undefined) { mode.relevance = 1; }; if (!mode.displayClassName) { mode.displayClassName = mode.className; }; }; }; }; function compileKeywords() { function compileModeKeywords(mode) { if (!mode.keywordGroups) { for (var key in mode.keywords) { if (!mode.keywords.hasOwnProperty(key)) continue; if (mode.keywords[key] instanceof Object) mode.keywordGroups = mode.keywords; else mode.keywordGroups = {'keyword': mode.keywords}; break; }; }; }; for (var i in LANGUAGES) { if (!LANGUAGES.hasOwnProperty(i)) continue; var language = LANGUAGES[i]; compileModeKeywords(language.defaultMode); for (var j = 0; j < language.modes.length; j++) { compileModeKeywords(language.modes[j]); }; }; }; function initialize() { if (initialize.called) return; initialize.called = true; compileModes(); compileKeywords(); selected_languages = LANGUAGES; }; function highlightBlock(block, tabReplace) { initialize(); try { var text = blockText(block); var language = blockLanguage(block); } catch (e) { if (e == 'No highlight') return; }; if (language) { var result = highlight(language, text).value; } else { var max_relevance = 0; for (var key in selected_languages) { if (!selected_languages.hasOwnProperty(key)) continue; var lang_result = highlight(key, text); var relevance = lang_result.keyword_count + lang_result.relevance; if (relevance > max_relevance) { max_relevance = relevance; var result = lang_result.value; language = key; }; }; }; if (result) { var class_name = block.className; if (!class_name.match(language)) { class_name += ' ' + language; }; var original = nodeStream(block); if (original.length) { var pre = document.createElement('pre'); pre.innerHTML = result; result = mergeStreams(original, nodeStream(pre), text); }; if (tabReplace) { result = result.replace(/^((<[^>]+>|\t)+)/gm, function(match, p1, offset, s) { return p1.replace(/\t/g, tabReplace); }); }; var container = document.createElement('div'); container.innerHTML = '
' + result + '
';
var environment = block.parentNode.parentNode;
environment.replaceChild(container.firstChild, block.parentNode);
};
};
function initHighlighting() {
if (initHighlighting.called)
return;
initHighlighting.called = true;
initialize();
if (arguments.length) {
for (var i = 0; i < arguments.length; i++) {
if (LANGUAGES[arguments[i]]) {
selected_languages[arguments[i]] = LANGUAGES[arguments[i]];
};
};
};
var pres = document.getElementsByTagName('pre');
for (var i = 0; i < pres.length; i++) {
var code = findCode(pres[i]);
if (code)
highlightBlock(code, hljs.tabReplace);
};
};
function initHighlightingOnLoad() {
var original_arguments = arguments;
var handler = function(){initHighlighting.apply(null, original_arguments)};
if (window.addEventListener) {
window.addEventListener('DOMContentLoaded', handler, false);
window.addEventListener('load', handler, false);
} else if (window.attachEvent)
window.attachEvent('onload', handler);
else
window.onload = handler;
};
this.LANGUAGES = LANGUAGES;
this.initHighlightingOnLoad = initHighlightingOnLoad;
this.highlightBlock = highlightBlock;
this.initHighlighting = initHighlighting;
this.IDENT_RE = '[a-zA-Z][a-zA-Z0-9_]*';
this.UNDERSCORE_IDENT_RE = '[a-zA-Z_][a-zA-Z0-9_]*';
this.NUMBER_RE = '\\b\\d+(\\.\\d+)?';
this.C_NUMBER_RE = '\\b(0x[A-Za-z0-9]+|\\d+(\\.\\d+)?)';
this.RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|\\.|-|-=|/|/=|:|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~';
this.APOS_STRING_MODE = {
className: 'string',
begin: '\'', end: '\'',
illegal: '\\n',
contains: ['escape'],
relevance: 0
};
this.QUOTE_STRING_MODE = {
className: 'string',
begin: '"', end: '"',
illegal: '\\n',
contains: ['escape'],
relevance: 0
};
this.BACKSLASH_ESCAPE = {
className: 'escape',
begin: '\\\\.', end: '^', noMarkup: true,
relevance: 0
};
this.C_LINE_COMMENT_MODE = {
className: 'comment',
begin: '//', end: '$',
relevance: 0
};
this.C_BLOCK_COMMENT_MODE = {
className: 'comment',
begin: '/\\*', end: '\\*/'
};
this.HASH_COMMENT_MODE = {
className: 'comment',
begin: '#', end: '$'
};
this.C_NUMBER_MODE = {
className: 'number',
begin: this.C_NUMBER_RE, end: '^',
relevance: 0
};
}();
var initHighlightingOnLoad = hljs.initHighlightingOnLoad;