ep_codepad
Version:
Turn etherpad into a realtime collaborative development environment
1,437 lines (1,339 loc) • 393 kB
JavaScript
var hljs = new function() {
try {
/* Utility functions */
function escape(value) {
return value.replace(/&/gm, '&').replace(/</gm, '<').replace(/>/gm, '>');
}
function tag(node) {
return node.nodeName.toLowerCase();
}
function testRe(re, lexeme) {
var match = re && re.exec(lexeme);
return match && match.index == 0;
}
function blockLanguage(block) {
var classes = (block.className + ' ' + (block.parentNode ? block.parentNode.className : '')).split(/\s+/);
classes = classes.map(function(c) {
return c.replace(/^lang(uage)?-/, '');
});
return classes.filter(function(c) {
return getLanguage(c) || /no(-?)highlight/.test(c);
})[0];
}
function inherit(parent, obj) {
var result = {};
for (var key in parent)
result[key] = parent[key];
if (obj)
for (var key in obj)
result[key] = obj[key];
return result;
};
/* 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.nodeType == 1) {
result.push({
event: 'start',
offset: offset,
node: child
});
offset = _nodeStream(child, offset);
// Prevent void elements from having an end tag that would actually
// double them in the output. There are more void elements in HTML
// but we list only those realistically expected in code display.
if (!tag(child).match(/br|hr|img|input/)) {
result.push({
event: 'stop',
offset: offset,
node: child
});
}
}
}
return offset;
})(node, 0);
return result;
}
function mergeStreams(original, highlighted, value) {
var processed = 0;
var result = '';
var nodeStack = [];
function selectStream() {
if (!original.length || !highlighted.length) {
return original.length ? original : highlighted;
}
if (original[0].offset != highlighted[0].offset) {
return (original[0].offset < highlighted[0].offset) ? original : highlighted;
}
/*
To avoid starting the stream just before it should stop the order is
ensured that original always starts first and closes last:
if (event1 == 'start' && event2 == 'start')
return original;
if (event1 == 'start' && event2 == 'stop')
return highlighted;
if (event1 == 'stop' && event2 == 'start')
return original;
if (event1 == 'stop' && event2 == 'stop')
return highlighted;
... which is collapsed to:
*/
return highlighted[0].event == 'start' ? original : highlighted;
}
function open(node) {
function attr_str(a) {
return ' ' + a.nodeName + '="' + escape(a.value) + '"';
}
result += '<' + tag(node) + Array.prototype.map.call(node.attributes, attr_str).join('') + '>';
}
function close(node) {
result += '</' + tag(node) + '>';
}
function render(event) {
(event.event == 'start' ? open : close)(event.node);
}
while (original.length || highlighted.length) {
var stream = selectStream();
result += escape(value.substr(processed, stream[0].offset - processed));
processed = stream[0].offset;
if (stream == original) {
/*
On any opening or closing tag of the original markup we first close
the entire highlighted node stack, then render the original tag along
with all the following original tags at the same offset and then
reopen all the tags on the highlighted stack.
*/
nodeStack.reverse().forEach(close);
do {
render(stream.splice(0, 1)[0]);
stream = selectStream();
} while (stream == original && stream.length && stream[0].offset == processed);
nodeStack.reverse().forEach(open);
} else {
if (stream[0].event == 'start') {
nodeStack.push(stream[0].node);
} else {
nodeStack.pop();
}
render(stream.splice(0, 1)[0]);
}
}
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;
mode.keywords = mode.keywords || mode.beginKeywords;
if (mode.keywords) {
var compiled_keywords = {};
var flatten = function(className, str) {
if (language.case_insensitive) {
str = str.toLowerCase();
}
str.split(' ').forEach(function(kw) {
var pair = kw.split('|');
compiled_keywords[pair[0]] = [className, pair[1] ? Number(pair[1]) : 1];
});
};
if (typeof mode.keywords == 'string') { // string
flatten('keyword', mode.keywords);
} else {
Object.keys(mode.keywords).forEach(function(className) {
flatten(className, mode.keywords[className]);
});
}
mode.keywords = compiled_keywords;
}
mode.lexemesRe = langRe(mode.lexemes || /\b[A-Za-z0-9_]+\b/, true);
if (parent) {
if (mode.beginKeywords) {
mode.begin = '\\b(' + mode.beginKeywords.split(' ').join('|') + ')\\b';
}
if (!mode.begin)
mode.begin = /\B|\b/;
mode.beginRe = langRe(mode.begin);
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 = [];
}
var expanded_contains = [];
mode.contains.forEach(function(c) {
if (c.variants) {
c.variants.forEach(function(v) {
expanded_contains.push(inherit(c, v));
});
} else {
expanded_contains.push(c == 'self' ? mode : c);
}
});
mode.contains = expanded_contains;
mode.contains.forEach(function(c) {
compileMode(c, mode);
});
if (mode.starts) {
compileMode(mode.starts, parent);
}
var terminators =
mode.contains.map(function(c) {
return c.beginKeywords ? '\\.?(' + c.begin + ')\\.?' : c.begin;
})
.concat([mode.terminator_end, mode.illegal])
.map(reStr)
.filter(Boolean);
mode.terminators = terminators.length ? langRe(terminators.join('|'), true) : {
exec: function(s) {
return null;
}
};
}
compileMode(language);
}
/*
Core highlighting function. Accepts a language name, or an alias, and a
string with the code to highlight. Returns an object with the following
properties:
- relevance (int)
- value (an HTML string with highlighting markup)
*/
function highlight(name, value, ignore_illegals, continuation) {
function subMode(lexeme, mode) {
for (var i = 0; i < mode.contains.length; i++) {
if (testRe(mode.contains[i].beginRe, lexeme)) {
return mode.contains[i];
}
}
}
function endOfMode(mode, lexeme) {
if (testRe(mode.endRe, lexeme)) {
return mode;
}
if (mode.endsWithParent) {
return endOfMode(mode.parent, lexeme);
}
}
function isIllegal(lexeme, mode) {
return !ignore_illegals && testRe(mode.illegalRe, lexeme);
}
function keywordMatch(mode, match) {
var match_str = language.case_insensitive ? match[0].toLowerCase() : match[0];
return mode.keywords.hasOwnProperty(match_str) && mode.keywords[match_str];
}
function buildSpan(classname, insideSpan, leaveOpen, noPrefix) {
var classPrefix = noPrefix ? '' : options.classPrefix,
openSpan = '<span class="' + classPrefix,
closeSpan = leaveOpen ? '' : '</span>';
openSpan += classname + '">';
return openSpan + insideSpan + closeSpan;
}
function processKeywords() {
if (!top.keywords)
return escape(mode_buffer);
var result = '';
var last_index = 0;
top.lexemesRe.lastIndex = 0;
var match = top.lexemesRe.exec(mode_buffer);
while (match) {
result += escape(mode_buffer.substr(last_index, match.index - last_index));
var keyword_match = keywordMatch(top, match);
if (keyword_match) {
relevance += keyword_match[1];
result += buildSpan(keyword_match[0], escape(match[0]));
} else {
result += escape(match[0]);
}
last_index = top.lexemesRe.lastIndex;
match = top.lexemesRe.exec(mode_buffer);
}
return result + escape(mode_buffer.substr(last_index));
}
function processSubLanguage() {
if (top.subLanguage && !languages[top.subLanguage]) {
return escape(mode_buffer);
}
var result = top.subLanguage ? highlight(top.subLanguage, mode_buffer, true, continuations[top.subLanguage]) : highlightAuto(mode_buffer);
// Counting embedded language score towards the host language may be disabled
// with zeroing the containing mode relevance. Usecase in point is Markdown that
// allows XML everywhere and makes every XML snippet to have a much larger Markdown
// score.
if (top.relevance > 0) {
relevance += result.relevance;
}
if (top.subLanguageMode == 'continuous') {
continuations[top.subLanguage] = result.top;
}
return buildSpan(result.language, result.value, false, true);
}
function processBuffer() {
return top.subLanguage !== undefined ? processSubLanguage() : processKeywords();
}
function startNewMode(mode, lexeme) {
var markup = mode.className ? buildSpan(mode.className, '', true) : '';
if (mode.returnBegin) {
result += markup;
mode_buffer = '';
} else if (mode.excludeBegin) {
result += escape(lexeme) + markup;
mode_buffer = '';
} else {
result += markup;
mode_buffer = lexeme;
}
top = Object.create(mode, {
parent: {
value: top
}
});
}
function processLexeme(buffer, lexeme) {
mode_buffer += buffer;
if (lexeme === undefined) {
result += processBuffer();
return 0;
}
var new_mode = subMode(lexeme, top);
if (new_mode) {
result += processBuffer();
startNewMode(new_mode, lexeme);
return new_mode.returnBegin ? 0 : lexeme.length;
}
var end_mode = endOfMode(top, lexeme);
if (end_mode) {
var origin = top;
if (!(origin.returnEnd || origin.excludeEnd)) {
mode_buffer += lexeme;
}
result += processBuffer();
do {
if (top.className) {
result += '</span>';
}
relevance += top.relevance;
top = top.parent;
} while (top != end_mode.parent);
if (origin.excludeEnd) {
result += escape(lexeme);
}
mode_buffer = '';
if (end_mode.starts) {
startNewMode(end_mode.starts, '');
}
return origin.returnEnd ? 0 : lexeme.length;
}
if (isIllegal(lexeme, top))
throw new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.className || '<unnamed>') + '"');
/*
Parser should not reach this point as all types of lexemes should be caught
earlier, but if it does due to some bug make sure it advances at least one
character forward to prevent infinite looping.
*/
mode_buffer += lexeme;
return lexeme.length || 1;
}
var language = getLanguage(name);
if (!language) {
throw new Error('Unknown language: "' + name + '"');
}
compileLanguage(language);
var top = continuation || language;
var continuations = {}; // keep continuations for sub-languages
var result = '';
for (var current = top; current != language; current = current.parent) {
if (current.className) {
result = buildSpan(current.className, '', true) + result;
}
}
var mode_buffer = '';
var relevance = 0;
try {
var match, count, index = 0;
while (true) {
// CODEPAD additional condiion. top.terminators is undefined?
if (typeof top.terminators === 'undefined') break;
top.terminators.lastIndex = index;
match = top.terminators.exec(value);
if (!match)
break;
count = processLexeme(value.substr(index, match.index - index), match[0]);
index = match.index + count;
}
processLexeme(value.substr(index));
for (var current = top; current.parent; current = current.parent) { // close dangling modes
if (current.className) {
result += '</span>';
}
};
return {
relevance: relevance,
value: result,
language: name,
top: top
};
} catch (e) {
if (e.message.indexOf('Illegal') != -1) {
return {
relevance: 0,
value: escape(value)
};
} else {
throw e;
}
}
}
/*
Highlighting with language detection. Accepts a string with the code to
highlight. Returns an object with the following properties:
- language (detected language)
- relevance (int)
- value (an HTML string with highlighting markup)
- second_best (object with the same structure for second-best heuristically
detected language, may be absent)
*/
function highlightAuto(text, languageSubset) {
languageSubset = languageSubset || options.languages || Object.keys(languages);
var result = {
relevance: 0,
value: escape(text)
};
var second_best = result;
languageSubset.forEach(function(name) {
if (!getLanguage(name)) {
return;
}
var current = highlight(name, text, false);
current.language = name;
if (current.relevance > second_best.relevance) {
second_best = current;
}
if (current.relevance > result.relevance) {
second_best = result;
result = current;
}
});
if (second_best.language) {
result.second_best = second_best;
}
return result;
}
/*
Post-processing of the highlighted markup:
- replace TABs with something more useful
- replace real line-breaks with '<br>' for non-pre containers
*/
function fixMarkup(value) {
if (options.tabReplace) {
value = value.replace(/^((<[^>]+>|\t)+)/gm, function(match, p1, offset, s) {
return p1.replace(/\t/g, options.tabReplace);
});
}
if (options.useBR) {
value = value.replace(/\n/g, '<br>');
}
return value;
}
function buildClassName(prevClassName, currentLang, resultLang) {
var language = currentLang ? aliases[currentLang] : resultLang,
result = [prevClassName.trim(), 'hljs'];
if (language) {
result.push(language);
}
return result.join(' ').trim();
}
/*
Applies highlighting to a DOM node containing code. Accepts a DOM node and
two optional parameters for fixMarkup.
*/
function highlightBlock(block) {
var language = blockLanguage(block);
if (/no(-?)highlight/.test(language))
return;
var node;
if (options.useBR) {
node = document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
node.innerHTML = block.innerHTML.replace(/\n/g, '').replace(/<br[ \/]*>/g, '\n');
} else {
node = block;
}
var text = node.textContent;
var result = language ? highlight(language, text, true) : highlightAuto(text);
var originalStream = nodeStream(node);
if (originalStream.length) {
var resultNode = document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
resultNode.innerHTML = result.value;
result.value = mergeStreams(originalStream, nodeStream(resultNode), text);
}
result.value = fixMarkup(result.value);
block.innerHTML = result.value;
block.className = buildClassName(block.className, language, result.language);
block.result = {
language: result.language,
re: result.relevance
};
if (result.second_best) {
block.second_best = {
language: result.second_best.language,
re: result.second_best.relevance
};
}
}
var options = {
classPrefix: 'hljs-',
tabReplace: null,
useBR: false,
languages: undefined
};
/*
Updates highlight.js global options with values passed in the form of an object
*/
function configure(user_options) {
options = inherit(options, user_options);
}
/*
Applies highlighting to all <pre><code>..</code></pre> blocks on a page.
*/
function initHighlighting() {
if (initHighlighting.called)
return;
initHighlighting.called = true;
var blocks = document.querySelectorAll('pre code');
Array.prototype.forEach.call(blocks, highlightBlock);
}
/*
Attaches highlighting to the page load event.
*/
function initHighlightingOnLoad() {
addEventListener('DOMContentLoaded', initHighlighting, false);
addEventListener('load', initHighlighting, false);
}
var languages = {};
var aliases = {};
function registerLanguage(name, language) {
var lang = languages[name] = language(this);
if (lang.aliases) {
lang.aliases.forEach(function(alias) {
aliases[alias] = name;
});
}
}
function listLanguages() {
return Object.keys(languages);
}
function getLanguage(name) {
return languages[name] || languages[aliases[name]];
}
/* Interface definition */
this.highlight = highlight;
this.highlightAuto = highlightAuto;
this.fixMarkup = fixMarkup;
this.highlightBlock = highlightBlock;
this.configure = configure;
this.initHighlighting = initHighlighting;
this.initHighlightingOnLoad = initHighlightingOnLoad;
this.registerLanguage = registerLanguage;
this.listLanguages = listLanguages;
this.getLanguage = getLanguage;
this.inherit = inherit;
// Common regexps
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 = '(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)'; // 0x..., 0..., decimal, float
this.BINARY_NUMBER_RE = '\\b(0b[01]+)'; // 0b...
this.RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~';
// ep_codepad specials curly braces
this.CODEPAD_CB = {
className: 'cb',
begin: '{|}'
};
//this.CODEPAD_OCB = {
// className: 'ocb',
// begin: '{'
//};
//this.CODEPAD_CCB = {
// className: 'ccb',
// begin: '}'
//};
// Common modes
this.BACKSLASH_ESCAPE = {
begin: '\\\\[\\s\\S]',
relevance: 0
};
this.APOS_STRING_MODE = {
className: 'string',
begin: '\'',
end: '\'',
illegal: '\\n',
contains: [this.BACKSLASH_ESCAPE]
};
this.QUOTE_STRING_MODE = {
className: 'string',
begin: '"',
end: '"',
illegal: '\\n',
contains: [this.BACKSLASH_ESCAPE]
};
this.PHRASAL_WORDS_MODE = {
begin: /\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such)\b/
};
this.C_LINE_COMMENT_MODE = {
className: 'comment',
begin: '//',
end: '$',
contains: [this.PHRASAL_WORDS_MODE]
};
this.C_BLOCK_COMMENT_MODE = {
className: 'comment',
begin: '/\\*',
end: '\\*/',
contains: [this.PHRASAL_WORDS_MODE]
};
this.HASH_COMMENT_MODE = {
className: 'comment',
begin: '#',
end: '$',
contains: [this.PHRASAL_WORDS_MODE]
};
this.NUMBER_MODE = {
className: 'number',
begin: this.NUMBER_RE,
relevance: 0
};
this.C_NUMBER_MODE = {
className: 'number',
begin: this.C_NUMBER_RE,
relevance: 0
};
this.BINARY_NUMBER_MODE = {
className: 'number',
begin: this.BINARY_NUMBER_RE,
relevance: 0
};
this.CSS_NUMBER_MODE = {
className: 'number',
begin: this.NUMBER_RE + '(' +
'%|em|ex|ch|rem' +
'|vw|vh|vmin|vmax' +
'|cm|mm|in|pt|pc|px' +
'|deg|grad|rad|turn' +
'|s|ms' +
'|Hz|kHz' +
'|dpi|dpcm|dppx' +
')?',
relevance: 0
};
this.REGEXP_MODE = {
className: 'regexp',
begin: /\//,
end: /\/[gimuy]*/,
illegal: /\n/,
contains: [
this.BACKSLASH_ESCAPE, {
begin: /\[/,
end: /\]/,
relevance: 0,
contains: [this.BACKSLASH_ESCAPE]
}
]
};
this.TITLE_MODE = {
className: 'title',
begin: this.IDENT_RE,
relevance: 0
};
this.UNDERSCORE_TITLE_MODE = {
className: 'title',
begin: this.UNDERSCORE_IDENT_RE,
relevance: 0
};
} catch (e) {
if (e) throw e;
}
}();
hljs.registerLanguage('elixir', function(hljs) {
var ELIXIR_IDENT_RE = '[a-zA-Z_][a-zA-Z0-9_]*(\\!|\\?)?';
var ELIXIR_METHOD_RE = '[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?';
var ELIXIR_KEYWORDS =
'and false then defined module in return redo retry end for true self when ' +
'next until do begin unless nil break not case cond alias while ensure or ' +
'include use alias fn quote';
var SUBST = {
className: 'subst',
begin: '#\\{', end: '}',
lexemes: ELIXIR_IDENT_RE,
keywords: ELIXIR_KEYWORDS
};
var STRING = {
className: 'string',
contains: [hljs.BACKSLASH_ESCAPE, SUBST],
variants: [
{
begin: /'/, end: /'/
},
{
begin: /"/, end: /"/
}
]
};
var PARAMS = {
endsWithParent: true, returnEnd: true,
lexemes: ELIXIR_IDENT_RE,
keywords: ELIXIR_KEYWORDS,
relevance: 0
};
var FUNCTION = {
className: 'function',
beginKeywords: 'def defmacro', end: /\bdo\b/,
contains: [
hljs.inherit(hljs.TITLE_MODE, {
begin: ELIXIR_METHOD_RE,
starts: PARAMS
})
]
};
var CLASS = hljs.inherit(FUNCTION, {
className: 'class',
beginKeywords: 'defmodule defrecord', end: /\bdo\b|$|;/
})
var ELIXIR_DEFAULT_CONTAINS = [
STRING,
hljs.HASH_COMMENT_MODE,
CLASS,
FUNCTION,
{
className: 'constant',
begin: '(\\b[A-Z_]\\w*(.)?)+',
relevance: 0
},
{
className: 'symbol',
begin: ':',
contains: [STRING, {begin: ELIXIR_METHOD_RE}],
relevance: 0
},
{
className: 'symbol',
begin: ELIXIR_IDENT_RE + ':',
relevance: 0
},
{
className: 'number',
begin: '(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b',
relevance: 0
},
{
className: 'variable',
begin: '(\\$\\W)|((\\$|\\@\\@?)(\\w+))'
},
{
begin: '->'
},
{ // regexp container
begin: '(' + hljs.RE_STARTERS_RE + ')\\s*',
contains: [
hljs.HASH_COMMENT_MODE,
{
className: 'regexp',
illegal: '\\n',
contains: [hljs.BACKSLASH_ESCAPE, SUBST],
variants: [
{
begin: '/', end: '/[a-z]*'
},
{
begin: '%r\\[', end: '\\][a-z]*'
}
]
}
],
relevance: 0
}
];
SUBST.contains = ELIXIR_DEFAULT_CONTAINS;
PARAMS.contains = ELIXIR_DEFAULT_CONTAINS;
return {
lexemes: ELIXIR_IDENT_RE,
keywords: ELIXIR_KEYWORDS,
contains: ELIXIR_DEFAULT_CONTAINS
};
});
hljs.registerLanguage('dos', function(hljs) {
var COMMENT = {
className: 'comment',
begin: /@?rem\b/, end: /$/,
relevance: 10
};
var LABEL = {
className: 'label',
begin: '^\\s*[A-Za-z._?][A-Za-z0-9_$#@~.?]*(:|\\s+label)',
relevance: 0
};
return {
aliases: ['bat', 'cmd'],
case_insensitive: true,
keywords: {
flow: 'if else goto for in do call exit not exist errorlevel defined',
operator: 'equ neq lss leq gtr geq',
keyword: 'shift cd dir echo setlocal endlocal set pause copy',
stream: 'prn nul lpt3 lpt2 lpt1 con com4 com3 com2 com1 aux',
winutils: 'ping net ipconfig taskkill xcopy ren del',
built_in: 'append assoc at attrib break cacls cd chcp chdir chkdsk chkntfs cls cmd color ' +
'comp compact convert date dir diskcomp diskcopy doskey erase fs ' +
'find findstr format ftype graftabl help keyb label md mkdir mode more move path ' +
'pause print popd pushd promt rd recover rem rename replace restore rmdir shift' +
'sort start subst time title tree type ver verify vol',
},
contains: [
{
className: 'envvar', begin: /%%[^ ]|%[^ ]+?%|![^ ]+?!/
},
{
className: 'function',
begin: LABEL.begin, end: 'goto:eof',
contains: [
hljs.inherit(hljs.TITLE_MODE, {begin: '([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*'}),
COMMENT
]
},
{
className: 'number', begin: '\\b\\d+',
relevance: 0
},
COMMENT
]
};
});
hljs.registerLanguage('go', function(hljs) {
var GO_KEYWORDS = {
keyword:
'break default func interface select case map struct chan else goto package switch ' +
'const fallthrough if range type continue for import return var go defer',
constant:
'true false iota nil',
typename:
'bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 ' +
'uint16 uint32 uint64 int uint uintptr rune',
built_in:
'append cap close complex copy imag len make new panic print println real recover delete'
};
return {
aliases: ["golang"],
keywords: GO_KEYWORDS,
illegal: '</',
contains: [
hljs.C_LINE_COMMENT_MODE,
hljs.C_BLOCK_COMMENT_MODE,
hljs.QUOTE_STRING_MODE,
{
className: 'string',
begin: '\'', end: '[^\\\\]\''
},
{
className: 'string',
begin: '`', end: '`'
},
{
className: 'number',
begin: '[^a-zA-Z_0-9](\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s)(\\+|\\-)?\\d+)?',
relevance: 0
},
hljs.C_NUMBER_MODE
]
};
});
hljs.registerLanguage('vala', function(hljs) {
return {
keywords: {
keyword:
// Value types
'char uchar unichar int uint long ulong short ushort int8 int16 int32 int64 uint8 ' +
'uint16 uint32 uint64 float double bool struct enum string void ' +
// Reference types
'weak unowned owned ' +
// Modifiers
'async signal static abstract interface override ' +
// Control Structures
'while do for foreach else switch case break default return try catch ' +
// Visibility
'public private protected internal ' +
// Other
'using new this get set const stdout stdin stderr var',
built_in:
'DBus GLib CCode Gee Object',
literal:
'false true null'
},
contains: [
{
className: 'class',
beginKeywords: 'class interface delegate namespace', end: '{', excludeEnd: true,
illegal: '[^,:\\n\\s\\.]',
contains: [
hljs.UNDERSCORE_TITLE_MODE
]
},
hljs.C_LINE_COMMENT_MODE,
hljs.C_BLOCK_COMMENT_MODE,
{
className: 'string',
begin: '"""', end: '"""',
relevance: 5
},
hljs.APOS_STRING_MODE,
hljs.QUOTE_STRING_MODE,
hljs.C_NUMBER_MODE,
{
className: 'preprocessor',
begin: '^#', end: '$',
relevance: 2
},
{
className: 'constant',
begin: ' [A-Z_]+ ',
relevance: 0
}
]
};
});
hljs.registerLanguage('perl', function(hljs) {
var PERL_KEYWORDS = 'getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ' +
'ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime ' +
'readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qq' +
'fileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent ' +
'shutdown dump chomp connect getsockname die socketpair close flock exists index shmget' +
'sub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr ' +
'unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 ' +
'getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline ' +
'endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand ' +
'mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink ' +
'getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr ' +
'untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link ' +
'getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller ' +
'lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and ' +
'sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 ' +
'chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach ' +
'tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedir' +
'ioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe ' +
'atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when';
var SUBST = {
className: 'subst',
begin: '[$@]\\{', end: '\\}',
keywords: PERL_KEYWORDS
};
var METHOD = {
begin: '->{', end: '}'
// contains defined later
};
var VAR = {
className: 'variable',
variants: [
{begin: /\$\d/},
{begin: /[\$\%\@](\^\w\b|#\w+(\:\:\w+)*|{\w+}|\w+(\:\:\w*)*)/},
{begin: /[\$\%\@][^\s\w{]/, relevance: 0}
]
};
var COMMENT = {
className: 'comment',
begin: '^(__END__|__DATA__)', end: '\\n$',
relevance: 5
};
var STRING_CONTAINS = [hljs.BACKSLASH_ESCAPE, SUBST, VAR];
var PERL_DEFAULT_CONTAINS = [
VAR,
hljs.HASH_COMMENT_MODE,
COMMENT,
{
className: 'comment',
begin: '^\\=\\w', end: '\\=cut', endsWithParent: true
},
METHOD,
{
className: 'string',
contains: STRING_CONTAINS,
variants: [
{
begin: 'q[qwxr]?\\s*\\(', end: '\\)',
relevance: 5
},
{
begin: 'q[qwxr]?\\s*\\[', end: '\\]',
relevance: 5
},
{
begin: 'q[qwxr]?\\s*\\{', end: '\\}',
relevance: 5
},
{
begin: 'q[qwxr]?\\s*\\|', end: '\\|',
relevance: 5
},
{
begin: 'q[qwxr]?\\s*\\<', end: '\\>',
relevance: 5
},
{
begin: 'qw\\s+q', end: 'q',
relevance: 5
},
{
begin: '\'', end: '\'',
contains: [hljs.BACKSLASH_ESCAPE]
},
{
begin: '"', end: '"'
},
{
begin: '`', end: '`',
contains: [hljs.BACKSLASH_ESCAPE]
},
{
begin: '{\\w+}',
contains: [],
relevance: 0
},
{
begin: '\-?\\w+\\s*\\=\\>',
contains: [],
relevance: 0
}
]
},
{
className: 'number',
begin: '(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b',
relevance: 0
},
{ // regexp container
begin: '(\\/\\/|' + hljs.RE_STARTERS_RE + '|\\b(split|return|print|reverse|grep)\\b)\\s*',
keywords: 'split return print reverse grep',
relevance: 0,
contains: [
hljs.HASH_COMMENT_MODE,
COMMENT,
{
className: 'regexp',
begin: '(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*',
relevance: 10
},
{
className: 'regexp',
begin: '(m|qr)?/', end: '/[a-z]*',
contains: [hljs.BACKSLASH_ESCAPE],
relevance: 0 // allows empty "//" which is a common comment delimiter in other languages
}
]
},
{
className: 'sub',
beginKeywords: 'sub', end: '(\\s*\\(.*?\\))?[;{]',
relevance: 5
},
{
className: 'operator',
begin: '-\\w\\b',
relevance: 0
}
];
SUBST.contains = PERL_DEFAULT_CONTAINS;
METHOD.contains = PERL_DEFAULT_CONTAINS;
return {
aliases: ['pl'],
keywords: PERL_KEYWORDS,
contains: PERL_DEFAULT_CONTAINS
};
});
hljs.registerLanguage('apache', function(hljs) {
var NUMBER = {className: 'number', begin: '[\\$%]\\d+'};
return {
aliases: ['apacheconf'],
case_insensitive: true,
contains: [
hljs.HASH_COMMENT_MODE,
{className: 'tag', begin: '</?', end: '>'},
{
className: 'keyword',
begin: /\w+/,
relevance: 0,
// keywords aren’t needed for highlighting per se, they only boost relevance
// for a very generally defined mode (starts with a word, ends with line-end
keywords: {
common:
'order deny allow setenv rewriterule rewriteengine rewritecond documentroot ' +
'sethandler errordocument loadmodule options header listen serverroot ' +
'servername'
},
starts: {
end: /$/,
relevance: 0,
keywords: {
literal: 'on off all'
},
contains: [
{
className: 'sqbracket',
begin: '\\s\\[', end: '\\]$'
},
{
className: 'cbracket',
begin: '[\\$%]\\{', end: '\\}',
contains: ['self', NUMBER]
},
NUMBER,
hljs.QUOTE_STRING_MODE
]
}
}
],
illegal: /\S/
};
});
hljs.registerLanguage('xml', function(hljs) {
var XML_IDENT_RE = '[A-Za-z0-9\\._:-]+';
var PHP = {
begin: /<\?(php)?(?!\w)/, end: /\?>/,
subLanguage: 'php', subLanguageMode: 'continuous'
};
var TAG_INTERNALS = {
endsWithParent: true,
illegal: /</,
relevance: 0,
contains: [
PHP,
{
className: 'attribute',
begin: XML_IDENT_RE,
relevance: 0
},
{
begin: '=',
relevance: 0,
contains: [
{
className: 'value',
contains: [PHP],
variants: [
{begin: /"/, end: /"/},
{begin: /'/, end: /'/},
{begin: /[^\s\/>]+/}
]
}
]
}
]
};
return {
aliases: ['html', 'xhtml', 'rss', 'atom', 'xsl', 'plist'],
case_insensitive: true,
contains: [
{
className: 'doctype',
begin: '<!DOCTYPE', end: '>',
relevance: 10,
contains: [{begin: '\\[', end: '\\]'}]
},
{
className: 'comment',
begin: '<!--', end: '-->',
relevance: 10
},
{
className: 'cdata',
begin: '<\\!\\[CDATA\\[', end: '\\]\\]>',
relevance: 10
},
{
className: 'tag',
/*
The lookahead pattern (?=...) ensures that 'begin' only matches
'<style' as a single word, followed by a whitespace or an
ending braket. The '$' is needed for the lexeme to be recognized
by hljs.subMode() that tests lexemes outside the stream.
*/
begin: '<style(?=\\s|>|$)', end: '>',
keywords: {title: 'style'},
contains: [TAG_INTERNALS],
starts: {
end: '</style>', returnEnd: true,
subLanguage: 'css'
}
},
{
className: 'tag',
// See the comment in the <style tag about the lookahead pattern
begin: '<script(?=\\s|>|$)', end: '>',
keywords: {title: 'script'},
contains: [TAG_INTERNALS],
starts: {
end: '</script>', returnEnd: true,
subLanguage: 'javascript'
}
},
{
begin: '<%', end: '%>',
subLanguage: 'vbscript'
},
PHP,
{
className: 'pi',
begin: /<\?\w+/, end: /\?>/,
relevance: 10
},
{
className: 'tag',
begin: '</?', end: '/?>',
contains: [
{
className: 'title', begin: /[^ \/><\n\t]+/, relevance: 0
},
TAG_INTERNALS
]
}
]
};
});
hljs.registerLanguage('dust', function(hljs) {
var EXPRESSION_KEYWORDS = 'if eq ne lt lte gt gte select default math sep';
return {
aliases: ['dst'],
case_insensitive: true,
subLanguage: 'xml', subLanguageMode: 'continuous',
contains: [
{
className: 'expression',
begin: '{', end: '}',
relevance: 0,
contains: [
{
className: 'begin-block', begin: '\#[a-zA-Z\-\ \.]+',
keywords: EXPRESSION_KEYWORDS
},
{
className: 'string',
begin: '"', end: '"'
},
{
className: 'end-block', begin: '\\\/[a-zA-Z\-\ \.]+',
keywords: EXPRESSION_KEYWORDS
},
{
className: 'variable', begin: '[a-zA-Z\-\.]+',
keywords: EXPRESSION_KEYWORDS,
relevance: 0
}
]
}
]
};
});
hljs.registerLanguage('nsis', function(hljs) {
var CONSTANTS = {
className: 'symbol',
begin: '\\$(ADMINTOOLS|APPDATA|CDBURN_AREA|CMDLINE|COMMONFILES32|COMMONFILES64|COMMONFILES|COOKIES|DESKTOP|DOCUMENTS|EXEDIR|EXEFILE|EXEPATH|FAVORITES|FONTS|HISTORY|HWNDPARENT|INSTDIR|INTERNET_CACHE|LANGUAGE|LOCALAPPDATA|MUSIC|NETHOOD|OUTDIR|PICTURES|PLUGINSDIR|PRINTHOOD|PROFILE|PROGRAMFILES32|PROGRAMFILES64|PROGRAMFILES|QUICKLAUNCH|RECENT|RESOURCES_LOCALIZED|RESOURCES|SENDTO|SMPROGRAMS|SMSTARTUP|STARTMENU|SYSDIR|TEMP|TEMPLATES|VIDEOS|WINDIR)'
};
var DEFINES = {
// ${defines}
className: 'constant',
begin: '\\$+{[a-zA-Z0-9_]+}'
};
var VARIABLES = {
// $variables
className: 'variable',
begin: '\\$+[a-zA-Z0-9_]+',
illegal: '\\(\\){}'
};
var LANGUAGES = {
// $(language_strings)
className: 'constant',
begin: '\\$+\\([a-zA-Z0-9_]+\\)'
};
var PARAMETERS = {
// command parameters
className: 'params',
begin: '(ARCHIVE|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_OFFLINE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY|HKCR|HKCU|HKDD|HKEY_CLASSES_ROOT|HKEY_CURRENT_CONFIG|HKEY_CURRENT_USER|HKEY_DYN_DATA|HKEY_LOCAL_MACHINE|HKEY_PERFORMANCE_DATA|HKEY_USERS|HKLM|HKPD|HKU|IDABORT|IDCANCEL|IDIGNORE|IDNO|IDOK|IDRETRY|IDYES|MB_ABORTRETRYIGNORE|MB_DEFBUTTON1|MB_DEFBUTTON2|MB_DEFBUTTON3|MB_DEFBUTTON4|MB_ICONEXCLAMATION|MB_ICONINFORMATION|MB_ICONQUESTION|MB_ICONSTOP|MB_OK|MB_OKCANCEL|MB_RETRYCANCEL|MB_RIGHT|MB_RTLREADING|MB_SETFOREGROUND|MB_TOPMOST|MB_USERICON|MB_YESNO|NORMAL|OFFLINE|READONLY|SHCTX|SHELL_CONTEXT|SYSTEM|TEMPORARY)'
};
var COMPILER ={
// !compiler_flags
className: 'constant',
begin: '\\!(addincludedir|addplugindir|appendfile|cd|define|delfile|echo|else|endif|error|execute|finalize|getdllversionsystem|ifdef|ifmacrodef|ifmacrondef|ifndef|if|include|insertmacro|macroend|macro|packhdr|searchparse|searchreplace|tempfile|undef|verbose|warning)'
};
return {
case_insensitive: false,
keywords: {
keyword:
'Abort AddBrandingImage AddSize AllowRootDirInstall AllowSkipFiles AutoCloseWindow BGFont BGGradient BrandingText BringToFront Call CallInstDLL Caption ChangeUI CheckBitmap ClearErrors CompletedText ComponentText CopyFiles CRCCheck CreateDirectory CreateFont CreateShortCut Delete DeleteINISec DeleteINIStr DeleteRegKey DeleteRegValue DetailPrint DetailsButtonText DirText DirVar DirVerify EnableWindow EnumRegKey EnumRegValue Exch Exec ExecShell ExecWait ExpandEnvStrings File FileBufSize FileClose FileErrorText FileOpen FileRead FileReadByte FileReadUTF16LE FileReadWord FileSeek FileWrite FileWriteByte FileWriteUTF16LE FileWriteWord FindClose FindFirst FindNext FindWindow FlushINI FunctionEnd GetCurInstType GetCurrentAddress GetDlgItem GetDLLVersion GetDLLVersionLocal GetErrorLevel GetFileTime GetFileTimeLocal GetFullPathName GetFunctionAddress GetInstDirError GetLabelAddress GetTempFileName Goto HideWindow Icon IfAbort IfErrors IfFileExists IfRebootFlag IfSilent InitPluginsDir InstallButtonText InstallColors InstallDir InstallDirRegKey InstProgressFlags InstType InstTypeGetText InstTypeSetText IntCmp IntCmpU IntFmt IntOp IsWindow LangString LicenseBkColor LicenseData LicenseForceSelection LicenseLangString LicenseText LoadLanguageFile LockWindow LogSet LogText ManifestDPIAware ManifestSupportedOS MessageBox MiscButtonText Name Nop OutFile Page PageCallbacks PageExEnd Pop Push Quit ReadEnvStr ReadINIStr ReadRegDWORD ReadRegStr Reboot RegDLL Rename RequestExecutionLevel ReserveFile Return RMDir SearchPath SectionEnd SectionGetFlags SectionGetInstTypes SectionGetSize SectionGetText SectionGroupEnd SectionIn SectionSetFlags SectionSetInstTypes SectionSetSize SectionSetText SendMessage SetAutoClose SetBrandingImage SetCompress SetCompressor SetCompressorDictSize SetCtlColors SetCurInstType SetDatablockOptimize SetDateSave SetDetailsPrint SetDetailsView SetErrorLevel SetErrors SetFileAttributes SetFont SetOutPath SetOverwrite SetPluginUnload SetRebootFlag SetRegView SetShellVarContext SetSilent ShowInstDetails ShowUninstDetails ShowWindow SilentInstall SilentUnInstall Sleep SpaceTexts StrCmp StrCmpS StrCpy StrLen SubCaption SubSectionEnd Unicode UninstallButtonText UninstallCaption UninstallIcon UninstallSubCaption UninstallText UninstPage UnRegDLL Var VIAddVersionKey VIFileVersion VIProductVersion WindowIcon WriteINIStr WriteRegBin WriteRegDWORD WriteRegExpandStr WriteRegStr WriteUninstaller XPStyle',
literal:
'admin all auto both colored current false force hide highest lastused leave listonly none normal notset off on open print show silent silentlog smooth textonly true user '
},
contains: [
hljs.HASH_COMMENT_MODE,
hljs.C_BLOCK_COMMENT_MODE,
{
className: 'string',
begin: '"', end: '"',
illegal: '\\n',
contains: [
{ // $\n, $\r, $\t, $$
className: 'symbol',
begin: '\\$(\\\\(n|r|t)|\\$)'
},
CONSTANTS,
DEFINES,
VARIABLES,
LANGUAGES
]
},
{ // line comments
className: 'comment',
begin: ';', end: '$',
relevance: 0
},
{
className: 'function',
beginKeywords: 'Function PageEx Section SectionGroup SubSection', end: '$'
},
COMPILER,
DEFINES,
VARIABLES,
LANGUAGES,
PARAMETERS,
hljs.NUMBER_MODE,
{ // plug::ins
className: 'literal',
begin: hljs.IDENT_RE + '::' + hljs.IDENT_RE
}
]
};
});
hljs.registerLanguage('nginx', function(hljs) {
var VAR = {
className: 'variable',
variants: [
{begin: /\$\d+/},
{begin: /\$\{/, end: /}/},
{begin: '[\\$\\@]' + hljs.UNDERSCO