/* Syntax highlighting with language autodetection. http://softwaremaniacs.org/soft/highlight/ */ function() { /* Utility functions */ function escape(value) { return value.replace(/&/gm, '&').replace(//gm, '>'); } function findCode(pre) { for (var node = pre.firstChild; node; node = node.nextSibling) { if (node.nodeName == 'CODE') return node; if (!(node.nodeType == 3 && node.nodeValue.match(/\s+/))) break; } } function blockText(block, ignoreNewLines) { return Array.prototype.map.call(block.childNodes, function(node) { if (node.nodeType == 3) { return ignoreNewLines ? node.nodeValue.replace(/\n/g, '') : node.nodeValue; } if (node.nodeName == 'BR') { return '\n'; } return blockText(node, ignoreNewLines); }).join(''); } function blockLanguage(block) { var classes = (block.className + ' ' + (block.parentNode ? block.parentNode.className : '')).split(/\s+/); classes = classes.map(function(c) {return c.replace(/^language-/, '')}); for (var i = 0; i < classes.length; i++) { if (languages[classes[i]] || classes[i] == 'no-highlight') { return classes[i]; } } } /* Stream merging */ function nodeStream(node) { var result = []; (function _nodeStream(node, offset) { for (var child = node.firstChild; child; child = child.nextSibling) { if (child.nodeType == 3) offset += child.nodeValue.length; else if (child.nodeName == 'BR') offset += 1; else if (child.nodeType == 1) { result.push({ event: 'start', offset: offset, node: child }); offset = _nodeStream(child, offset); result.push({ event: 'stop', offset: offset, node: child }); } } 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 { /* To avoid starting the stream just before it should stop the order is ensured that stream1 always starts first and closes last: if (event1 == 'start' && event2 == 'start') return stream1; if (event1 == 'start' && event2 == 'stop') return stream2; if (event1 == 'stop' && event2 == 'start') return stream1; if (event1 == 'stop' && event2 == 'stop') return stream2; ... which is collapsed to: */ return stream2[0].event == 'start' ? stream1 : stream2; } } else { return stream1.length ? stream1 : stream2; } } function open(node) { function attr_str(a) {return ' ' + a.nodeName + '="' + escape(a.value) + '"'}; return '<' + node.nodeName + Array.prototype.map.call(node.attributes, attr_str).join('') + '>'; } 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 node, i = nodeStack.length; do { i--; node = nodeStack[i]; result += (''); } while (node != current.node); nodeStack.splice(i, 1); while (i < nodeStack.length) { result += open(nodeStack[i]); i++; } } } return result + escape(value.substr(processed)); } /* Initialization */ function compileLanguage(language) { function reStr(re) { return (re && re.source) || re; } function langRe(value, global) { return RegExp( reStr(value), 'm' + (language.case_insensitive ? 'i' : '') + (global ? 'g' : '') ); } function compileMode(mode, parent) { if (mode.compiled) return; mode.compiled = true; var keywords = []; // used later with beginWithKeyword but filled as a side-effect of keywords compilation if (mode.keywords) { var compiled_keywords = {}; function flatten(className, str) { str.split(' ').forEach(function(kw) { var pair = kw.split('|'); compiled_keywords[pair[0]] = [className, pair[1] ? Number(pair[1]) : 1]; keywords.push(pair[0]); }); } mode.lexemsRe = langRe(mode.lexems || hljs.IDENT_RE + '(?!\\.)', true); if (typeof mode.keywords == 'string') { // string flatten('keyword', mode.keywords) } else { for (var className in mode.keywords) { if (!mode.keywords.hasOwnProperty(className)) continue; flatten(className, mode.keywords[className]); } } mode.keywords = compiled_keywords; } if (parent) { if (mode.beginWithKeyword) { mode.begin = '\\b(' + keywords.join('|') + ')\\b(?!\\.)\\s*'; } mode.beginRe = langRe(mode.begin ? mode.begin : '\\B|\\b'); if (!mode.end && !mode.endsWithParent) mode.end = '\\B|\\b'; if (mode.end) mode.endRe = langRe(mode.end); mode.terminator_end = reStr(mode.end) || ''; if (mode.endsWithParent && parent.terminator_end) mode.terminator_end += (mode.end ? '|' : '') + parent.terminator_end; } if (mode.illegal) mode.illegalRe = langRe(mode.illegal); if (mode.relevance === undefined) mode.relevance = 1; if (!mode.contains) { mode.contains = []; } for (var i = 0; i < mode.contains.length; i++) { if (mode.contains[i] == 'self') { mode.contains[i] = mode; } compileMode(mode.contains[i], mode); } if (mode.starts) { compileMode(mode.starts, parent); } var terminators = []; for (var i = 0; i < mode.contains.length; i++) { terminators.push(reStr(mode.contains[i].begin)); } if (mode.terminator_end) { terminators.push(reStr(mode.terminator_end)); } if (mode.illegal) { terminators.push(reStr(mode.illegal)); } mode.terminators = terminators.length ? langRe(terminators.join('|'), true) : {exec: function(s) {return null;}}; } compileMode(language); }