| /* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+java+bash&plugins=line-highlight */ |
| self = (typeof window !== 'undefined') |
| ? window // if in browser |
| : ( |
| (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) |
| ? self // if in worker |
| : {} // if in node js |
| ); |
| |
| /** |
| * Prism: Lightweight, robust, elegant syntax highlighting |
| * MIT license http://www.opensource.org/licenses/mit-license.php/ |
| * @author Lea Verou http://lea.verou.me |
| */ |
| |
| var Prism = (function(){ |
| |
| // Private helper vars |
| var lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i; |
| |
| var _ = self.Prism = { |
| util: { |
| encode: function (tokens) { |
| if (tokens instanceof Token) { |
| return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias); |
| } else if (_.util.type(tokens) === 'Array') { |
| return tokens.map(_.util.encode); |
| } else { |
| return tokens.replace(/&/g, '&').replace(/</g, '<').replace(/\u00a0/g, ' '); |
| } |
| }, |
| |
| type: function (o) { |
| return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1]; |
| }, |
| |
| // Deep clone a language definition (e.g. to extend it) |
| clone: function (o) { |
| var type = _.util.type(o); |
| |
| switch (type) { |
| case 'Object': |
| var clone = {}; |
| |
| for (var key in o) { |
| if (o.hasOwnProperty(key)) { |
| clone[key] = _.util.clone(o[key]); |
| } |
| } |
| |
| return clone; |
| |
| case 'Array': |
| return o.slice(); |
| } |
| |
| return o; |
| } |
| }, |
| |
| languages: { |
| extend: function (id, redef) { |
| var lang = _.util.clone(_.languages[id]); |
| |
| for (var key in redef) { |
| lang[key] = redef[key]; |
| } |
| |
| return lang; |
| }, |
| |
| /** |
| * Insert a token before another token in a language literal |
| * As this needs to recreate the object (we cannot actually insert before keys in object literals), |
| * we cannot just provide an object, we need anobject and a key. |
| * @param inside The key (or language id) of the parent |
| * @param before The key to insert before. If not provided, the function appends instead. |
| * @param insert Object with the key/value pairs to insert |
| * @param root The object that contains `inside`. If equal to Prism.languages, it can be omitted. |
| */ |
| insertBefore: function (inside, before, insert, root) { |
| root = root || _.languages; |
| var grammar = root[inside]; |
| |
| if (arguments.length == 2) { |
| insert = arguments[1]; |
| |
| for (var newToken in insert) { |
| if (insert.hasOwnProperty(newToken)) { |
| grammar[newToken] = insert[newToken]; |
| } |
| } |
| |
| return grammar; |
| } |
| |
| var ret = {}; |
| |
| for (var token in grammar) { |
| |
| if (grammar.hasOwnProperty(token)) { |
| |
| if (token == before) { |
| |
| for (var newToken in insert) { |
| |
| if (insert.hasOwnProperty(newToken)) { |
| ret[newToken] = insert[newToken]; |
| } |
| } |
| } |
| |
| ret[token] = grammar[token]; |
| } |
| } |
| |
| // Update references in other language definitions |
| _.languages.DFS(_.languages, function(key, value) { |
| if (value === root[inside] && key != inside) { |
| this[key] = ret; |
| } |
| }); |
| |
| return root[inside] = ret; |
| }, |
| |
| // Traverse a language definition with Depth First Search |
| DFS: function(o, callback, type) { |
| for (var i in o) { |
| if (o.hasOwnProperty(i)) { |
| callback.call(o, i, o[i], type || i); |
| |
| if (_.util.type(o[i]) === 'Object') { |
| _.languages.DFS(o[i], callback); |
| } |
| else if (_.util.type(o[i]) === 'Array') { |
| _.languages.DFS(o[i], callback, i); |
| } |
| } |
| } |
| } |
| }, |
| |
| highlightAll: function(async, callback) { |
| var elements = document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'); |
| |
| for (var i=0, element; element = elements[i++];) { |
| _.highlightElement(element, async === true, callback); |
| } |
| }, |
| |
| highlightElement: function(element, async, callback) { |
| // Find language |
| var language, grammar, parent = element; |
| |
| while (parent && !lang.test(parent.className)) { |
| parent = parent.parentNode; |
| } |
| |
| if (parent) { |
| language = (parent.className.match(lang) || [,''])[1]; |
| grammar = _.languages[language]; |
| } |
| |
| if (!grammar) { |
| return; |
| } |
| |
| // Set language on the element, if not present |
| element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language; |
| |
| // Set language on the parent, for styling |
| parent = element.parentNode; |
| |
| if (/pre/i.test(parent.nodeName)) { |
| parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language; |
| } |
| |
| var code = element.textContent; |
| |
| if(!code) { |
| return; |
| } |
| |
| var env = { |
| element: element, |
| language: language, |
| grammar: grammar, |
| code: code |
| }; |
| |
| _.hooks.run('before-highlight', env); |
| |
| if (async && self.Worker) { |
| var worker = new Worker(_.filename); |
| |
| worker.onmessage = function(evt) { |
| env.highlightedCode = Token.stringify(JSON.parse(evt.data), language); |
| |
| _.hooks.run('before-insert', env); |
| |
| env.element.innerHTML = env.highlightedCode; |
| |
| callback && callback.call(env.element); |
| _.hooks.run('after-highlight', env); |
| }; |
| |
| worker.postMessage(JSON.stringify({ |
| language: env.language, |
| code: env.code |
| })); |
| } |
| else { |
| env.highlightedCode = _.highlight(env.code, env.grammar, env.language) |
| |
| _.hooks.run('before-insert', env); |
| |
| env.element.innerHTML = env.highlightedCode; |
| |
| callback && callback.call(element); |
| |
| _.hooks.run('after-highlight', env); |
| } |
| }, |
| |
| highlight: function (text, grammar, language) { |
| var tokens = _.tokenize(text, grammar); |
| return Token.stringify(_.util.encode(tokens), language); |
| }, |
| |
| tokenize: function(text, grammar, language) { |
| var Token = _.Token; |
| |
| var strarr = [text]; |
| |
| var rest = grammar.rest; |
| |
| if (rest) { |
| for (var token in rest) { |
| grammar[token] = rest[token]; |
| } |
| |
| delete grammar.rest; |
| } |
| |
| tokenloop: for (var token in grammar) { |
| if(!grammar.hasOwnProperty(token) || !grammar[token]) { |
| continue; |
| } |
| |
| var patterns = grammar[token]; |
| patterns = (_.util.type(patterns) === "Array") ? patterns : [patterns]; |
| |
| for (var j = 0; j < patterns.length; ++j) { |
| var pattern = patterns[j], |
| inside = pattern.inside, |
| lookbehind = !!pattern.lookbehind, |
| lookbehindLength = 0, |
| alias = pattern.alias; |
| |
| pattern = pattern.pattern || pattern; |
| |
| for (var i=0; i<strarr.length; i++) { // Don’t cache length as it changes during the loop |
| |
| var str = strarr[i]; |
| |
| if (strarr.length > text.length) { |
| // Something went terribly wrong, ABORT, ABORT! |
| break tokenloop; |
| } |
| |
| if (str instanceof Token) { |
| continue; |
| } |
| |
| pattern.lastIndex = 0; |
| |
| var match = pattern.exec(str); |
| |
| if (match) { |
| if(lookbehind) { |
| lookbehindLength = match[1].length; |
| } |
| |
| var from = match.index - 1 + lookbehindLength, |
| match = match[0].slice(lookbehindLength), |
| len = match.length, |
| to = from + len, |
| before = str.slice(0, from + 1), |
| after = str.slice(to + 1); |
| |
| var args = [i, 1]; |
| |
| if (before) { |
| args.push(before); |
| } |
| |
| var wrapped = new Token(token, inside? _.tokenize(match, inside) : match, alias); |
| |
| args.push(wrapped); |
| |
| if (after) { |
| args.push(after); |
| } |
| |
| Array.prototype.splice.apply(strarr, args); |
| } |
| } |
| } |
| } |
| |
| return strarr; |
| }, |
| |
| hooks: { |
| all: {}, |
| |
| add: function (name, callback) { |
| var hooks = _.hooks.all; |
| |
| hooks[name] = hooks[name] || []; |
| |
| hooks[name].push(callback); |
| }, |
| |
| run: function (name, env) { |
| var callbacks = _.hooks.all[name]; |
| |
| if (!callbacks || !callbacks.length) { |
| return; |
| } |
| |
| for (var i=0, callback; callback = callbacks[i++];) { |
| callback(env); |
| } |
| } |
| } |
| }; |
| |
| var Token = _.Token = function(type, content, alias) { |
| this.type = type; |
| this.content = content; |
| this.alias = alias; |
| }; |
| |
| Token.stringify = function(o, language, parent) { |
| if (typeof o == 'string') { |
| return o; |
| } |
| |
| if (Object.prototype.toString.call(o) == '[object Array]') { |
| return o.map(function(element) { |
| return Token.stringify(element, language, o); |
| }).join(''); |
| } |
| |
| var env = { |
| type: o.type, |
| content: Token.stringify(o.content, language, parent), |
| tag: 'span', |
| classes: ['token', o.type], |
| attributes: {}, |
| language: language, |
| parent: parent |
| }; |
| |
| if (env.type == 'comment') { |
| env.attributes['spellcheck'] = 'true'; |
| } |
| |
| if (o.alias) { |
| var aliases = _.util.type(o.alias) === 'Array' ? o.alias : [o.alias]; |
| Array.prototype.push.apply(env.classes, aliases); |
| } |
| |
| _.hooks.run('wrap', env); |
| |
| var attributes = ''; |
| |
| for (var name in env.attributes) { |
| attributes += name + '="' + (env.attributes[name] || '') + '"'; |
| } |
| |
| return '<' + env.tag + ' class="' + env.classes.join(' ') + '" ' + attributes + '>' + env.content + '</' + env.tag + '>'; |
| |
| }; |
| |
| if (!self.document) { |
| if (!self.addEventListener) { |
| // in Node.js |
| return self.Prism; |
| } |
| // In worker |
| self.addEventListener('message', function(evt) { |
| var message = JSON.parse(evt.data), |
| lang = message.language, |
| code = message.code; |
| |
| self.postMessage(JSON.stringify(_.util.encode(_.tokenize(code, _.languages[lang])))); |
| self.close(); |
| }, false); |
| |
| return self.Prism; |
| } |
| |
| // Get current script and highlight |
| var script = document.getElementsByTagName('script'); |
| |
| script = script[script.length - 1]; |
| |
| if (script) { |
| _.filename = script.src; |
| |
| if (document.addEventListener && !script.hasAttribute('data-manual')) { |
| document.addEventListener('DOMContentLoaded', _.highlightAll); |
| } |
| } |
| |
| return self.Prism; |
| |
| })(); |
| |
| if (typeof module !== 'undefined' && module.exports) { |
| module.exports = Prism; |
| } |
| ; |
| Prism.languages.markup = { |
| 'comment': /<!--[\w\W]*?-->/g, |
| 'prolog': /<\?.+?\?>/, |
| 'doctype': /<!DOCTYPE.+?>/, |
| 'cdata': /<!\[CDATA\[[\w\W]*?]]>/i, |
| 'tag': { |
| pattern: /<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|[^\s'">=]+))?\s*)*\/?>/gi, |
| inside: { |
| 'tag': { |
| pattern: /^<\/?[\w:-]+/i, |
| inside: { |
| 'punctuation': /^<\/?/, |
| 'namespace': /^[\w-]+?:/ |
| } |
| }, |
| 'attr-value': { |
| pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi, |
| inside: { |
| 'punctuation': /=|>|"/g |
| } |
| }, |
| 'punctuation': /\/?>/g, |
| 'attr-name': { |
| pattern: /[\w:-]+/g, |
| inside: { |
| 'namespace': /^[\w-]+?:/ |
| } |
| } |
| |
| } |
| }, |
| 'entity': /\&#?[\da-z]{1,8};/gi |
| }; |
| |
| // Plugin to make entity title show the real entity, idea by Roman Komarov |
| Prism.hooks.add('wrap', function(env) { |
| |
| if (env.type === 'entity') { |
| env.attributes['title'] = env.content.replace(/&/, '&'); |
| } |
| }); |
| ; |
| Prism.languages.css = { |
| 'comment': /\/\*[\w\W]*?\*\//g, |
| 'atrule': { |
| pattern: /@[\w-]+?.*?(;|(?=\s*{))/gi, |
| inside: { |
| 'punctuation': /[;:]/g |
| } |
| }, |
| 'url': /url\((["']?).*?\1\)/gi, |
| 'selector': /[^\{\}\s][^\{\};]*(?=\s*\{)/g, |
| 'property': /(\b|\B)[\w-]+(?=\s*:)/ig, |
| 'string': /("|')(\\?.)*?\1/g, |
| 'important': /\B!important\b/gi, |
| 'punctuation': /[\{\};:]/g, |
| 'function': /[-a-z0-9]+(?=\()/ig |
| }; |
| |
| if (Prism.languages.markup) { |
| Prism.languages.insertBefore('markup', 'tag', { |
| 'style': { |
| pattern: /<style[\w\W]*?>[\w\W]*?<\/style>/ig, |
| inside: { |
| 'tag': { |
| pattern: /<style[\w\W]*?>|<\/style>/ig, |
| inside: Prism.languages.markup.tag.inside |
| }, |
| rest: Prism.languages.css |
| }, |
| alias: 'language-css' |
| } |
| }); |
| |
| Prism.languages.insertBefore('inside', 'attr-value', { |
| 'style-attr': { |
| pattern: /\s*style=("|').+?\1/ig, |
| inside: { |
| 'attr-name': { |
| pattern: /^\s*style/ig, |
| inside: Prism.languages.markup.tag.inside |
| }, |
| 'punctuation': /^\s*=\s*['"]|['"]\s*$/, |
| 'attr-value': { |
| pattern: /.+/gi, |
| inside: Prism.languages.css |
| } |
| }, |
| alias: 'language-css' |
| } |
| }, Prism.languages.markup.tag); |
| }; |
| Prism.languages.clike = { |
| 'comment': [ |
| { |
| pattern: /(^|[^\\])\/\*[\w\W]*?\*\//g, |
| lookbehind: true |
| }, |
| { |
| pattern: /(^|[^\\:])\/\/.*?(\r?\n|$)/g, |
| lookbehind: true |
| } |
| ], |
| 'string': /("|')(\\?.)*?\1/g, |
| 'class-name': { |
| pattern: /((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/ig, |
| lookbehind: true, |
| inside: { |
| punctuation: /(\.|\\)/ |
| } |
| }, |
| 'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g, |
| 'boolean': /\b(true|false)\b/g, |
| 'function': { |
| pattern: /[a-z0-9_]+\(/ig, |
| inside: { |
| punctuation: /\(/ |
| } |
| }, |
| 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g, |
| 'operator': /[-+]{1,2}|!|<=?|>=?|={1,3}|&{1,2}|\|?\||\?|\*|\/|\~|\^|\%/g, |
| 'ignore': /&(lt|gt|amp);/gi, |
| 'punctuation': /[{}[\];(),.:]/g |
| }; |
| ; |
| Prism.languages.java = Prism.languages.extend('clike', { |
| 'keyword': /\b(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/g, |
| 'number': /\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp\-]+\b|\b\d*\.?\d+[e]?[\d]*[df]\b|\W\d*\.?\d+\b/gi, |
| 'operator': { |
| pattern: /(^|[^\.])(?:\+=|\+\+?|-=|--?|!=?|<{1,2}=?|>{1,3}=?|==?|&=|&&?|\|=|\|\|?|\?|\*=?|\/=?|%=?|\^=?|:|~)/gm, |
| lookbehind: true |
| } |
| });; |
| Prism.languages.bash = Prism.languages.extend('clike', { |
| 'comment': { |
| pattern: /(^|[^"{\\])(#.*?(\r?\n|$))/g, |
| lookbehind: true |
| }, |
| 'string': { |
| //allow multiline string |
| pattern: /("|')(\\?[\s\S])*?\1/g, |
| inside: { |
| //'property' class reused for bash variables |
| 'property': /\$([a-zA-Z0-9_#\?\-\*!@]+|\{[^\}]+\})/g |
| } |
| }, |
| 'keyword': /\b(if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)\b/g |
| }); |
| |
| Prism.languages.insertBefore('bash', 'keyword', { |
| //'property' class reused for bash variables |
| 'property': /\$([a-zA-Z0-9_#\?\-\*!@]+|\{[^}]+\})/g |
| }); |
| Prism.languages.insertBefore('bash', 'comment', { |
| //shebang must be before comment, 'important' class from css reused |
| 'important': /(^#!\s*\/bin\/bash)|(^#!\s*\/bin\/sh)/g |
| }); |
| ; |
| (function(){ |
| |
| if(!window.Prism) { |
| return; |
| } |
| |
| function $$(expr, con) { |
| return Array.prototype.slice.call((con || document).querySelectorAll(expr)); |
| } |
| |
| function hasClass(element, className) { |
| className = " " + className + " "; |
| return (" " + element.className + " ").replace(/[\n\t]/g, " ").indexOf(className) > -1 |
| } |
| |
| var CRLF = crlf = /\r?\n|\r/g; |
| |
| function highlightLines(pre, lines, classes) { |
| var ranges = lines.replace(/\s+/g, '').split(','), |
| offset = +pre.getAttribute('data-line-offset') || 0; |
| |
| var lineHeight = parseFloat(getComputedStyle(pre).lineHeight); |
| |
| var preTop = $(pre).offset().top; |
| |
| var preHeight = $(pre).height(); |
| var lineCount = $(pre).text().trim().split("\n").length; |
| var myLineHeight = preHeight/lineCount; |
| |
| for (var i=0, range; range = ranges[i++];) { |
| range = range.split('-'); |
| |
| var start = +range[0], |
| end = +range[1] || start; |
| |
| var line = document.createElement('div'); |
| |
| line.textContent = Array(end - start + 2).join(' \r\n'); |
| line.className = (classes || '') + ' line-highlight'; |
| |
| //if the line-numbers plugin is enabled, then there is no reason for this plugin to display the line numbers |
| if(!hasClass(pre, 'line-numbers') && false) { |
| line.setAttribute('data-start', start); |
| |
| if(end > start) { |
| line.setAttribute('data-end', end); |
| } |
| } |
| |
| |
| line.style.top = (start - offset - 1) * myLineHeight + 0.5 + 'px'; |
| |
| //allow this to play nicely with the line-numbers plugin |
| if(hasClass(pre, 'line-numbers') || true) { |
| //need to attack to pre as when line-numbers is enabled, the code tag is relatively which screws up the positioning |
| pre.appendChild(line); |
| } else { |
| (pre.querySelector('code') || pre).appendChild(line); |
| } |
| } |
| } |
| |
| function applyHash() { |
| var hash = location.hash.slice(1); |
| |
| // Remove pre-existing temporary lines |
| $$('.temporary.line-highlight').forEach(function (line) { |
| line.parentNode.removeChild(line); |
| }); |
| |
| var range = (hash.match(/\.([\d,-]+)$/) || [,''])[1]; |
| |
| if (!range || document.getElementById(hash)) { |
| return; |
| } |
| |
| var id = hash.slice(0, hash.lastIndexOf('.')), |
| pre = document.getElementById(id); |
| |
| if (!pre) { |
| return; |
| } |
| |
| if (!pre.hasAttribute('data-line')) { |
| pre.setAttribute('data-line', ''); |
| } |
| |
| highlightLines(pre, range, 'temporary '); |
| |
| document.querySelector('.temporary.line-highlight').scrollIntoView(); |
| } |
| |
| var fakeTimer = 0; // Hack to limit the number of times applyHash() runs |
| |
| Prism.hooks.add('after-highlight', function(env) { |
| var pre = env.element.parentNode; |
| var lines = pre && pre.getAttribute('data-line'); |
| |
| if (!pre || !lines || !/pre/i.test(pre.nodeName)) { |
| return; |
| } |
| |
| clearTimeout(fakeTimer); |
| |
| $$('.line-highlight', pre).forEach(function (line) { |
| line.parentNode.removeChild(line); |
| }); |
| |
| highlightLines(pre, lines); |
| |
| fakeTimer = setTimeout(applyHash, 1); |
| }); |
| |
| addEventListener('hashchange', applyHash); |
| |
| })(); |
| ; |