if (navigator.appVersion.indexOf("MSIE 8") == -1) { // Added to make prism not run on IE8 as it throws errors all over the place.
	/* http://prismjs.com/download.html?themes=prism&languages=markup+css+css-extras+clike+javascript+java+php+php-extras+coffeescript+scss+bash+c+cpp+python+sql+groovy+http+ruby+gherkin+csharp+go+nsis+aspnet&plugins=line-highlight+line-numbers+show-invisibles+autolinker+wpd+file-highlight+show-language */
	var self = (typeof window !== 'undefined') ? window : {};

	/**
	 * 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: {
				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
				insertBefore: function (inside, before, insert, root) {
					root = root || _.languages;
					var grammar = root[inside];
					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];
						}
					}

					return root[inside] = ret;
				},

				// Traverse a language definition with Depth First Search
				DFS: function (o, callback) {
					for (var i in o) {
						callback.call(o, i, o[i]);

						if (_.util.type(o) === 'Object') {
							_.languages.DFS(o[i], callback);
						}
					}
				}
			},

			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;
				}

				code = code.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' ');

				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) {
				return Token.stringify(_.tokenize(text, grammar), 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 pattern = grammar[token],
						inside = pattern.inside,
						lookbehind = !!pattern.lookbehind,
						lookbehindLength = 0;

					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);

							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) {
			this.type = type;
			this.content = content;
		};

		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';
			}

			_.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(_.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': /&lt;!--[\w\W]*?-->/g,
		'prolog': /&lt;\?.+?\?>/,
		'doctype': /&lt;!DOCTYPE.+?>/,
		'cdata': /&lt;!\[CDATA\[[\w\W]*?]]>/i,
		'tag': {
			pattern: /&lt;\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|[^\s'">=]+))?\s*)*\/?>/gi,
			inside: {
				'tag': {
					pattern: /^&lt;\/?[\w:-]+/i,
					inside: {
						'punctuation': /^&lt;\/?/,
						'namespace': /^[\w-]+?:/
					}
				},
				'attr-value': {
					pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi,
					inside: {
						'punctuation': /=|>|"/g
					}
				},
				'punctuation': /\/?>/g,
				'attr-name': {
					pattern: /[\w:-]+/g,
					inside: {
						'namespace': /^[\w-]+?:/
					}
				}

			}
		},
		'entity': /&amp;#?[\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(/&amp;/, '&');
		}
	});
	;
	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,
		'ignore': /&(lt|gt|amp);/gi,
		'punctuation': /[\{\};:]/g
	};

	if (Prism.languages.markup) {
		Prism.languages.insertBefore('markup', 'tag', {
			'style': {
				pattern: /(&lt;|<)style[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/style(>|&gt;)/ig,
				inside: {
					'tag': {
						pattern: /(&lt;|<)style[\w\W]*?(>|&gt;)|(&lt;|<)\/style(>|&gt;)/ig,
						inside: Prism.languages.markup.tag.inside
					},
					rest: Prism.languages.css
				}
			}
		});
	}
	;
	Prism.languages.css.selector = {
		pattern: /[^\{\}\s][^\{\}]*(?=\s*\{)/g,
		inside: {
			'pseudo-element': /:(?:after|before|first-letter|first-line|selection)|::[-\w]+/g,
			'pseudo-class': /:[-\w]+(?:\(.*\))?/g,
			'class': /\.[-:\.\w]+/g,
			'id': /#[-:\.\w]+/g
		}
	};

	Prism.languages.insertBefore('css', 'ignore', {
		'hexcode': /#[\da-f]{3,6}/gi,
		'entity': /\\[\da-f]{1,8}/gi,
		'number': /[\d%\.]+/g,
		'function': /(attr|calc|cross-fade|cycle|element|hsla?|image|lang|linear-gradient|matrix3d|matrix|perspective|radial-gradient|repeating-linear-gradient|repeating-radial-gradient|rgba?|rotatex|rotatey|rotatez|rotate3d|rotate|scalex|scaley|scalez|scale3d|scale|skewx|skewy|skew|steps|translatex|translatey|translatez|translate3d|translate|url|var)/ig
	});
	;
	Prism.languages.clike = {
		'comment': {
			pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\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}|!|&lt;=?|>=?|={1,3}|(&amp;){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,
		'ignore': /&(lt|gt|amp);/gi,
		'punctuation': /[{}[\];(),.:]/g
	};
	;
	Prism.languages.javascript = Prism.languages.extend('clike', {
		'keyword': /\b(var|let|if|else|while|do|for|return|in|instanceof|function|get|set|new|with|typeof|try|throw|catch|finally|null|break|continue|this)\b/g,
		'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g
	});

	Prism.languages.insertBefore('javascript', 'keyword', {
		'regex': {
			pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,
			lookbehind: true
		}
	});

	if (Prism.languages.markup) {
		Prism.languages.insertBefore('markup', 'tag', {
			'script': {
				pattern: /(&lt;|<)script[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/script(>|&gt;)/ig,
				inside: {
					'tag': {
						pattern: /(&lt;|<)script[\w\W]*?(>|&gt;)|(&lt;|<)\/script(>|&gt;)/ig,
						inside: Prism.languages.markup.tag.inside
					},
					rest: Prism.languages.javascript
				}
			}
		});
	}
	;
	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}|!|=?&lt;|=?&gt;|={1,2}|(&amp;){1,2}|\|?\||\?|\*|\/|%|\^|(&lt;){2}|($gt;){2,3}|:|~)/g,
			lookbehind: true
		}
	});
	;
	/**
	 * Original by Aaron Harun: http://aahacreative.com/2012/07/31/php-syntax-highlighting-prism/
	 * Modified by Miles Johnson: http://milesj.me
	 *
	 * Supports the following:
	 *    - Extends clike syntax
	 *    - Support for PHP 5.3 and 5.4 (namespaces, traits, etc)
	 *    - Smarter constant and function matching
	 *
	 * Adds the following new token classes:
	 *    constant, delimiter, variable, function, package
	 */

	Prism.languages.php = Prism.languages.extend('clike', {
		'keyword': /\b(and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\b/ig,
		'constant': /\b[A-Z0-9_]{2,}\b/g,
		'comment': {
			pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])(\/\/|#).*?(\r?\n|$))/g,
			lookbehind: true
		},
	});

	Prism.languages.insertBefore('php', 'keyword', {
		'delimiter': /(\?>|&lt;\?php|&lt;\?)/ig,
		'variable': /(\$\w+)\b/ig,
		'package': {
			pattern: /(\\|namespace\s+|use\s+)[\w\\]+/g,
			lookbehind: true,
			inside: {
				punctuation: /\\/
			}
		}
	});

// Must be defined after the function pattern
	Prism.languages.insertBefore('php', 'operator', {
		'property': {
			pattern: /(->)[\w]+/g,
			lookbehind: true
		}
	});

// Add HTML support of the markup language exists
	if (Prism.languages.markup) {

		// Tokenize all inline PHP blocks that are wrapped in <?php ?>
		// This allows for easy PHP + markup highlighting
		Prism.hooks.add('before-highlight', function (env) {
			if (env.language !== 'php') {
				return;
			}

			env.tokenStack = [];

			env.code = env.code.replace(/(?:&lt;\?php|&lt;\?|<\?php|<\?)[\w\W]*?(?:\?&gt;|\?>)/ig, function (match) {
				env.tokenStack.push(match);

				return '{{{PHP' + env.tokenStack.length + '}}}';
			});
		});

		// Re-insert the tokens after highlighting
		Prism.hooks.add('after-highlight', function (env) {
			if (env.language !== 'php') {
				return;
			}

			for (var i = 0, t; t = env.tokenStack[i]; i++) {
				env.highlightedCode = env.highlightedCode.replace('{{{PHP' + (i + 1) + '}}}', Prism.highlight(t, env.grammar, 'php'));
			}

			env.element.innerHTML = env.highlightedCode;
		});

		// Wrap tokens in classes that are missing them
		Prism.hooks.add('wrap', function (env) {
			if (env.language === 'php' && env.type === 'markup') {
				env.content = env.content.replace(/(\{\{\{PHP[0-9]+\}\}\})/g, "<span class=\"token php\">$1</span>");
			}
		});

		// Add the rules before all others
		Prism.languages.insertBefore('php', 'comment', {
			'markup': {
				pattern: /(&lt;|<)[^?]\/?(.*?)(>|&gt;)/g,
				inside: Prism.languages.markup
			},
			'php': /\{\{\{PHP[0-9]+\}\}\}/g
		});
	}
	;
	Prism.languages.insertBefore('php', 'variable', {
		'this': /\$this/g,
		'global': /\$_?(GLOBALS|SERVER|GET|POST|FILES|REQUEST|SESSION|ENV|COOKIE|HTTP_RAW_POST_DATA|argc|argv|php_errormsg|http_response_header)/g,
		'scope': {
			pattern: /\b[\w\\]+::/g,
			inside: {
				keyword: /(static|self|parent)/,
				punctuation: /(::|\\)/
			}
		}
	});
	;
	Prism.languages.coffeescript = Prism.languages.extend('javascript', {
		'block-comment': /([#]{3}\s*\r?\n(.*\s*\r*\n*)\s*?\r?\n[#]{3})/g,
		'comment': /(\s|^)([#]{1}[^#^\r^\n]{2,}?(\r?\n|$))/g,
		'keyword': /\b(this|window|delete|class|extends|namespace|extend|ar|let|if|else|while|do|for|each|of|return|in|instanceof|new|with|typeof|try|catch|finally|null|undefined|break|continue)\b/g
	});

	Prism.languages.insertBefore('coffeescript', 'keyword', {
		'function': {
			pattern: /[a-z|A-z]+\s*[:|=]\s*(\([.|a-z\s|,|:|{|}|\"|\'|=]*\))?\s*-&gt;/gi,
			inside: {
				'function-name': /[_?a-z-|A-Z-]+(\s*[:|=])| @[_?$?a-z-|A-Z-]+(\s*)| /g,
				'operator': /[-+]{1,2}|!|=?&lt;|=?&gt;|={1,2}|(&amp;){1,2}|\|?\||\?|\*|\//g
			}
		},
		'attr-name': /[_?a-z-|A-Z-]+(\s*:)| @[_?$?a-z-|A-Z-]+(\s*)| /g
	});
	;
	Prism.languages.scss = Prism.languages.extend('css', {
		'comment': {
			pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g,
			lookbehind: true
		},
		// aturle is just the @***, not the entire rule (to highlight var & stuffs)
		// + add ability to highlight number & unit for media queries
		'atrule': /@[\w-]+(?=\s+(\(|\{|;))/gi,
		// url, compassified
		'url': /([-a-z]+-)*url(?=\()/gi,
		// CSS selector regex is not appropriate for Sass
		// since there can be lot more things (var, @ directive, nesting..)
		// a selector must start at the end of a property or after a brace (end of other rules or nesting)
		// it can contain some caracters that aren't used for defining rules or end of selector, & (parent selector), or interpolated variable
		// the end of a selector is found when there is no rules in it ( {} or {\s}) or if there is a property (because an interpolated var
		// can "pass" as a selector- e.g: proper#{$erty})
		// this one was ard to do, so please be careful if you edit this one :)
		'selector': /([^@;\{\}\(\)]?([^@;\{\}\(\)]|&amp;|\#\{\$[-_\w]+\})+)(?=\s*\{(\}|\s|[^\}]+(:|\{)[^\}]+))/gm
	});

	Prism.languages.insertBefore('scss', 'atrule', {
		'keyword': /@(if|else if|else|for|each|while|import|extend|debug|warn|mixin|include|function|return|content)|(?=@for\s+\$[-_\w]+\s)+from/i
	});

	Prism.languages.insertBefore('scss', 'property', {
		// var and interpolated vars
		'variable': /((\$[-_\w]+)|(#\{\$[-_\w]+\}))/i
	});

	Prism.languages.insertBefore('scss', 'ignore', {
		'placeholder': /%[-_\w]+/i,
		'statement': /\B!(default|optional)\b/gi,
		'boolean': /\b(true|false)\b/g,
		'null': /\b(null)\b/g,
		'operator': /\s+([-+]{1,2}|={1,2}|!=|\|?\||\?|\*|\/|\%)\s+/g
	});
	;
	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
	});
	;
	Prism.languages.c = Prism.languages.extend('clike', {
		'keyword': /\b(asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/g,
		'operator': /[-+]{1,2}|!=?|&lt;{1,2}=?|&gt;{1,2}=?|\-&gt;|={1,2}|\^|~|%|(&amp;){1,2}|\|?\||\?|\*|\//g
	});

	Prism.languages.insertBefore('c', 'keyword', {
		//property class reused for macro statements
		'property': {
			pattern: /#[a-zA-Z]+\ .*/g,
			inside: {
				property: /&lt;[a-zA-Z.]+>/g
			}
		}
	});
	;
	Prism.languages.cpp = Prism.languages.extend('c', {
		'keyword': /\b(alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|delete\[\]|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|new\[\]|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/g,
		'operator': /[-+]{1,2}|!=?|&lt;{1,2}=?|&gt;{1,2}=?|\-&gt;|:{1,2}|={1,2}|\^|~|%|(&amp;){1,2}|\|?\||\?|\*|\/|\b(and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/g
	});
	;
	Prism.languages.python = {
		'comment': {
			pattern: /(^|[^\\])#.*?(\r?\n|$)/g,
			lookbehind: true
		},
		'string': /("|')(\\?.)*?\1/g,
		'keyword': /\b(as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/g,
		'boolean': /\b(True|False)\b/g,
		'number': /\b-?(0x)?\d*\.?[\da-f]+\b/g,
		'operator': /[-+]{1,2}|=?&lt;|=?&gt;|!|={1,2}|(&){1,2}|(&amp;){1,2}|\|?\||\?|\*|\/|~|\^|%|\b(or|and|not)\b/g,
		'ignore': /&(lt|gt|amp);/gi,
		'punctuation': /[{}[\];(),.:]/g
	};

	;
	Prism.languages.sql = {
		'comment': {
			pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|((--)|(\/\/)|#).*?(\r?\n|$))/g,
			lookbehind: true
		},
		'string': /("|')(\\?.)*?\1/g,
		'keyword': /\b(ACTION|ADD|AFTER|ALGORITHM|ALTER|ANALYZE|APPLY|AS|ASC|AUTHORIZATION|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADE|CASCADED|CASE|CHAIN|CHAR VARYING|CHARACTER VARYING|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLUMN|COLUMNS|COMMENT|COMMIT|COMMITTED|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATA|DATABASE|DATABASES|DATETIME|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DOUBLE PRECISION|DROP|DUMMY|DUMP|DUMPFILE|DUPLICATE KEY|ELSE|ENABLE|ENCLOSED BY|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPE|ESCAPED BY|EXCEPT|EXEC|EXECUTE|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR|FOR EACH ROW|FORCE|FOREIGN|FREETEXT|FREETEXTTABLE|FROM|FULL|FUNCTION|GEOMETRY|GEOMETRYCOLLECTION|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|IDENTITY|IDENTITY_INSERT|IDENTITYCOL|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTO|INVOKER|ISOLATION LEVEL|JOIN|KEY|KEYS|KILL|LANGUAGE SQL|LAST|LEFT|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONGBLOB|LONGTEXT|MATCH|MATCHED|MEDIUMBLOB|MEDIUMINT|MEDIUMTEXT|MERGE|MIDDLEINT|MODIFIES SQL DATA|MODIFY|MULTILINESTRING|MULTIPOINT|MULTIPOLYGON|NATIONAL|NATIONAL CHAR VARYING|NATIONAL CHARACTER|NATIONAL CHARACTER VARYING|NATIONAL VARCHAR|NATURAL|NCHAR|NCHAR VARCHAR|NEXT|NO|NO SQL|NOCHECK|NOCYCLE|NONCLUSTERED|NULLIF|NUMERIC|OF|OFF|OFFSETS|ON|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPTIMIZE|OPTION|OPTIONALLY|ORDER|OUT|OUTER|OUTFILE|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREV|PRIMARY|PRINT|PRIVILEGES|PROC|PROCEDURE|PUBLIC|PURGE|QUICK|RAISERROR|READ|READS SQL DATA|READTEXT|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEATABLE|REPLICATION|REQUIRE|RESTORE|RESTRICT|RETURN|RETURNS|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROWCOUNT|ROWGUIDCOL|ROWS?|RTREE|RULE|SAVE|SAVEPOINT|SCHEMA|SELECT|SERIAL|SERIALIZABLE|SESSION|SESSION_USER|SET|SETUSER|SHARE MODE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|START|STARTING BY|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLE|TABLES|TABLESPACE|TEMPORARY|TEMPTABLE|TERMINATED BY|TEXT|TEXTSIZE|THEN|TIMESTAMP|TINYBLOB|TINYINT|TINYTEXT|TO|TOP|TRAN|TRANSACTION|TRANSACTIONS|TRIGGER|TRUNCATE|TSEQUAL|TYPE|TYPES|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNPIVOT|UPDATE|UPDATETEXT|USAGE|USE|USER|USING|VALUE|VALUES|VARBINARY|VARCHAR|VARCHARACTER|VARYING|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH|WITH ROLLUP|WITHIN|WORK|WRITE|WRITETEXT)\b/gi,
		'boolean': /\b(TRUE|FALSE|NULL)\b/gi,
		'number': /\b-?(0x)?\d*\.?[\da-f]+\b/g,
		'operator': /\b(ALL|AND|ANY|BETWEEN|EXISTS|IN|LIKE|NOT|OR|IS|UNIQUE|CHARACTER SET|COLLATE|DIV|OFFSET|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b|[-+]{1}|!|=?&lt;|=?&gt;|={1}|(&amp;){1,2}|\|?\||\?|\*|\//gi,
		'ignore': /&(lt|gt|amp);/gi,
		'punctuation': /[;[\]()`,.]/g
	};
	;
	Prism.languages.groovy = Prism.languages.extend('clike', {
		'keyword': /\b(as|def|in|abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|trait|transient|try|void|volatile|while)\b/g,
		'string': /("""|''')[\W\w]*?\1|("|'|\/)[\W\w]*?\2|(\$\/)(\$\/\$|[\W\w])*?\/\$/g,
		'number': /\b0b[01_]+\b|\b0x[\da-f_]+(\.[\da-f_p\-]+)?\b|\b[\d_]+(\.[\d_]+[e]?[\d]*)?[glidf]\b|[\d_]+(\.[\d_]+)?\b/gi,
		'operator': {
			pattern: /(^|[^.])(={0,2}~|\?\.|\*?\.@|\.&amp;|\.{1,2}(?!\.)|\.{2}(&lt;)?(?=\w)|->|\?:|[-+]{1,2}|!|&lt;=>|>{1,3}|(&lt;){1,2}|={1,2}|(&amp;){1,2}|\|{1,2}|\?|\*{1,2}|\/|\^|%)/g,
			lookbehind: true
		},
		'punctuation': /\.+|[{}[\];(),:$]/g
	});

	Prism.languages.insertBefore('groovy', 'punctuation', {
		'spock-block': /\b(setup|given|when|then|and|cleanup|expect|where):/g
	});

	Prism.languages.insertBefore('groovy', 'function', {
		'annotation': {
			pattern: /(^|[^.])@\w+/,
			lookbehind: true
		}
	});

	Prism.hooks.add('wrap', function (env) {
		if (env.language === 'groovy' && env.type === 'string') {
			var delimiter = env.content[0];

			if (delimiter != "'") {
				var pattern = /([^\\])(\$(\{.*?\}|[\w\.]+))/;
				if (delimiter === '$') {
					pattern = /([^\$])(\$(\{.*?\}|[\w\.]+))/;
				}
				env.content = Prism.highlight(env.content, {
					'expression': {
						pattern: pattern,
						lookbehind: true,
						inside: Prism.languages.groovy
					}
				});

				env.classes.push(delimiter === '/' ? 'regex' : 'gstring');
			}
		}
	});
	;
	Prism.languages.http = {
		'request-line': {
			pattern: /^(POST|GET|PUT|DELETE|OPTIONS|PATCH|TRACE|CONNECT)\b\shttps?:\/\/\S+\sHTTP\/[0-9.]+/g,
			inside: {
				// HTTP Verb
				property: /^\b(POST|GET|PUT|DELETE|OPTIONS|PATCH|TRACE|CONNECT)\b/g,
				// Path or query argument
				'attr-name': /:\w+/g
			}
		},
		'response-status': {
			pattern: /^HTTP\/1.[01] [0-9]+.*/g,
			inside: {
				// Status, e.g. 200 OK
				property: /[0-9]+[A-Z\s-]+$/g
			}
		},
		// HTTP header name
		keyword: /^[\w-]+:(?=.+)/gm
	};

// Create a mapping of Content-Type headers to language definitions
	var httpLanguages = {
		'application/json': Prism.languages.javascript,
		'application/xml': Prism.languages.markup,
		'text/xml': Prism.languages.markup,
		'text/html': Prism.languages.markup
	};

// Insert each content type parser that has its associated language
// currently loaded.
	for (var contentType in httpLanguages) {
		if (httpLanguages[contentType]) {
			var options = {};
			options[contentType] = {
				pattern: new RegExp('(content-type:\\s*' + contentType + '[\\w\\W]*?)\\n\\n[\\w\\W]*', 'gi'),
				lookbehind: true,
				inside: {
					rest: httpLanguages[contentType]
				}
			};
			Prism.languages.insertBefore('http', 'keyword', options);
		}
	}
	;
	/**
	 * Original by Samuel Flores
	 *
	 * Adds the following new token classes:
	 *    constant, builtin, variable, symbol, regex
	 */
	Prism.languages.ruby = Prism.languages.extend('clike', {
		'comment': /#[^\r\n]*(\r?\n|$)/g,
		'keyword': /\b(alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|false|for|if|in|module|new|next|nil|not|or|raise|redo|require|rescue|retry|return|self|super|then|throw|true|undef|unless|until|when|while|yield)\b/g,
		'builtin': /\b(Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Stat|File|Fixnum|Fload|Hash|Integer|IO|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|String|Struct|TMS|Symbol|ThreadGroup|Thread|Time|TrueClass)\b/,
		'constant': /\b[A-Z][a-zA-Z_0-9]*[?!]?\b/g
	});

	Prism.languages.insertBefore('ruby', 'keyword', {
		'regex': {
			pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,
			lookbehind: true
		},
		'variable': /[@$]+\b[a-zA-Z_][a-zA-Z_0-9]*[?!]?\b/g,
		'symbol': /:\b[a-zA-Z_][a-zA-Z_0-9]*[?!]?\b/g
	});
	;
// TODO:
// 		- Support for outline parameters
// 		- Support for tables

	Prism.languages.gherkin = {
		'comment': {
			pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|((#)|(\/\/)).*?(\r?\n|$))/g,
			lookbehind: true
		},
		'string': /("|')(\\?.)*?\1/g,
		'atrule': /\b(And|Given|When|Then|In order to|As an|I want to|As a)\b/g,
		'keyword': /\b(Scenario Outline|Scenario|Feature|Background|Story)\b/g,
	};
	;
	Prism.languages.csharp = Prism.languages.extend('clike', {
		'keyword': /\b(abstract|as|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|private|protected|public|readonly|ref|return|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|virtual|void|volatile|while|add|alias|ascending|async|await|descending|dynamic|from|get|global|group|into|join|let|orderby|partial|remove|select|set|value|var|where|yield)\b/g,
		'string': /@?("|')(\\?.)*?\1/g,
		'preprocessor': /^\s*#.*/gm,
		'number': /\b-?(0x)?\d*\.?\d+\b/g
	});
	;
	Prism.languages.go = Prism.languages.extend('clike', {
		'keyword': /\b(break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/g,
		'builtin': /\b(bool|byte|complex(64|128)|error|float(32|64)|rune|string|u?int(8|16|32|64|)|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(ln)?|real|recover)\b/g,
		'boolean': /\b(_|iota|nil|true|false)\b/g,
		'operator': /([(){}\[\]]|[*\/%^!]=?|\+[=+]?|-[>=-]?|\|[=|]?|>[=>]?|&lt;(&lt;|[=-])?|==?|&amp;(&amp;|=|^=?)?|\.(\.\.)?|[,;]|:=?)/g,
		'number': /\b(-?(0x[a-f\d]+|(\d+\.?\d*|\.\d+)(e[-+]?\d+)?)i?)\b/ig,
		'string': /("|'|`)(\\?.|\r|\n)*?\1/g
	});
	delete Prism.languages.go['class-name'];
	;
	/**
	 * Original by Jan T. Sott (http://github.com/idleberg)
	 *
	 * Includes all commands and plug-ins shipped with NSIS 3.0a2
	 */
	Prism.languages.nsis = {
		'comment': {
			pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])(#|;).*?(\r?\n|$))/g,
			lookbehind: true
		},
		'string': /("|')(\\?.)*?\1/g,
		'keyword': /\b(Abort|Add(BrandingImage|Size)|AdvSplash|Allow(RootDirInstall|SkipFiles)|AutoCloseWindow|Banner|BG(Font|Gradient|Image)|BrandingText|BringToFront|Call(\b|InstDLL)|Caption|ChangeUI|CheckBitmap|ClearErrors|CompletedText|ComponentText|CopyFiles|CRCCheck|Create(Directory|Font|ShortCut)|Delete(\b|INISec|INIStr|RegKey|RegValue)|Detail(Print|sButtonText)|Dialer|Dir(Text|Var|Verify)|EnableWindow|Enum(RegKey|RegValue)|Exch|Exec(\b|Shell|Wait)|ExpandEnvStrings|File(\b|BufSize|Close|ErrorText|Open|Read|ReadByte|ReadUTF16LE|ReadWord|WriteUTF16LE|Seek|Write|WriteByte|WriteWord)|Find(Close|First|Next|Window)|FlushINI|Get(CurInstType|CurrentAddress|DlgItem|DLLVersion|DLLVersionLocal|ErrorLevel|FileTime|FileTimeLocal|FullPathName|Function(\b|Address|End)|InstDirError|LabelAddress|TempFileName)|Goto|HideWindow|Icon|If(Abort|Errors|FileExists|RebootFlag|Silent)|InitPluginsDir|Install(ButtonText|Colors|Dir|DirRegKey)|InstProgressFlags|Inst(Type|TypeGetText|TypeSetText)|Int(Cmp|CmpU|Fmt|Op)|IsWindow|Lang(DLL|String)|License(BkColor|Data|ForceSelection|LangString|Text)|LoadLanguageFile|LockWindow|Log(Set|Text)|Manifest(DPIAware|SupportedOS)|Math|MessageBox|MiscButtonText|Name|Nop|ns(Dialogs|Exec)|NSISdl|OutFile|Page(\b|Callbacks)|Pop|Push|Quit|Read(EnvStr|INIStr|RegDWORD|RegStr)|Reboot|RegDLL|Rename|RequestExecutionLevel|ReserveFile|Return|RMDir|SearchPath|Section(\b|End|GetFlags|GetInstTypes|GetSize|GetText|Group|In|SetFlags|SetInstTypes|SetSize|SetText)|SendMessage|Set(AutoClose|BrandingImage|Compress|Compressor|CompressorDictSize|CtlColors|CurInstType|DatablockOptimize|DateSave|DetailsPrint|DetailsView|ErrorLevel|Errors|FileAttributes|Font|OutPath|Overwrite|PluginUnload|RebootFlag|RegView|ShellVarContext|Silent)|Show(InstDetails|UninstDetails|Window)|Silent(Install|UnInstall)|Sleep|SpaceTexts|Splash|StartMenu|Str(Cmp|CmpS|Cpy|Len)|SubCaption|System|Unicode|Uninstall(ButtonText|Caption|Icon|SubCaption|Text)|UninstPage|UnRegDLL|UserInfo|Var|VI(AddVersionKey|FileVersion|ProductVersion)|VPatch|WindowIcon|WriteINIStr|WriteRegBin|WriteRegDWORD|WriteRegExpandStr|Write(RegStr|Uninstaller)|XPStyle)\b/g,
		'property': /\b(admin|all|auto|both|colored|false|force|hide|highest|lastused|leave|listonly|none|normal|notset|off|on|open|print|show|silent|silentlog|smooth|textonly|true|user|ARCHIVE|FILE_(ATTRIBUTE_ARCHIVE|ATTRIBUTE_NORMAL|ATTRIBUTE_OFFLINE|ATTRIBUTE_READONLY|ATTRIBUTE_SYSTEM|ATTRIBUTE_TEMPORARY)|HK(CR|CU|DD|LM|PD|U)|HKEY_(CLASSES_ROOT|CURRENT_CONFIG|CURRENT_USER|DYN_DATA|LOCAL_MACHINE|PERFORMANCE_DATA|USERS)|ID(ABORT|CANCEL|IGNORE|NO|OK|RETRY|YES)|MB_(ABORTRETRYIGNORE|DEFBUTTON1|DEFBUTTON2|DEFBUTTON3|DEFBUTTON4|ICONEXCLAMATION|ICONINFORMATION|ICONQUESTION|ICONSTOP|OK|OKCANCEL|RETRYCANCEL|RIGHT|RTLREADING|SETFOREGROUND|TOPMOST|USERICON|YESNO)|NORMAL|OFFLINE|READONLY|SHCTX|SHELL_CONTEXT|SYSTEM|TEMPORARY)\b/g,
		'variable': /(\$(\(|\{)?[-_\w]+)(\)|\})?/i,
		'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,
		'operator': /[-+]{1,2}|&lt;=?|>=?|={1,3}|(&amp;){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,
		'punctuation': /[{}[\];(),.:]/g,
		'important': /\!(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)\b/gi,
	};
	;
	Prism.languages.aspnet = Prism.languages.extend('markup', {
		'page-directive tag': {
			pattern: /(<|&lt;)%\s*@.*%>/gi,
			inside: {
				'page-directive tag': /&lt;%\s*@\s*(?:Assembly|Control|Implements|Import|Master|MasterType|OutputCache|Page|PreviousPageType|Reference|Register)?|%>/ig,
				rest: Prism.languages.markup.tag.inside
			}
		},
		'directive tag': {
			pattern: /(<|&lt;)%.*%>/gi,
			inside: {
				'directive tag': /(<|&lt;)%\s*?[$=%#:]{0,2}|%>/gi,
				rest: Prism.languages.csharp
			}
		}
	});

// match directives of attribute value foo="<% Bar %>"
	Prism.languages.insertBefore('inside', 'punctuation', {
		'directive tag': Prism.languages.aspnet['directive tag']
	}, Prism.languages.aspnet.tag.inside["attr-value"]);

	Prism.languages.insertBefore('aspnet', 'comment', {
		'asp comment': /&lt;%--[\w\W]*?--%>/g
	});

// script runat="server" contains csharp, not javascript
	Prism.languages.insertBefore('aspnet', Prism.languages.javascript ? 'script' : 'tag', {
		'asp script': {
			pattern: /(&lt;|<)script(?=.*runat=['"]?server['"]?)[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/script(>|&gt;)/ig,
			inside: {
				tag: {
					pattern: /&lt;\/?script\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|\w+))?\s*)*\/?>/gi,
					inside: Prism.languages.aspnet.tag.inside
				},
				rest: Prism.languages.csharp || {}
			}
		}
	});

// Hacks to fix eager tag matching finishing too early: <script src="<% Foo.Bar %>"> => <script src="<% Foo.Bar %>
	if (Prism.languages.aspnet.style) {
		Prism.languages.aspnet.style.inside.tag.pattern = /&lt;\/?style\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|\w+))?\s*)*\/?>/gi;
		Prism.languages.aspnet.style.inside.tag.inside = Prism.languages.aspnet.tag.inside;
	}
	if (Prism.languages.aspnet.script) {
		Prism.languages.aspnet.script.inside.tag.pattern = Prism.languages.aspnet['asp script'].inside.tag.pattern
		Prism.languages.aspnet.script.inside.tag.inside = Prism.languages.aspnet.tag.inside;
	}
	;
	(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);

			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')) {
					line.setAttribute('data-start', start);

					if (end > start) {
						line.setAttribute('data-end', end);
					}
				}

				line.style.top = (start - offset - 1) * lineHeight + 'px';

				//allow this to play nicely with the line-numbers plugin
				if (hasClass(pre, 'line-numbers')) {
					//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);

	})();
	;
	Prism.hooks.add('after-highlight', function (env) {
		// works only for <code> wrapped inside <pre data-line-numbers> (not inline)
		var pre = env.element.parentNode;
		if (!pre || !/pre/i.test(pre.nodeName) || pre.className.indexOf('line-numbers') === -1) {
			return;
		}

		var linesNum = (1 + env.code.split('\n').length);
		var lineNumbersWrapper;

		lines = new Array(linesNum);
		lines = lines.join('<span></span>');

		lineNumbersWrapper = document.createElement('span');
		lineNumbersWrapper.className = 'line-numbers-rows';
		lineNumbersWrapper.innerHTML = lines;

		if (pre.hasAttribute('data-start')) {
			pre.style.counterReset = 'linenumber ' + (parseInt(pre.getAttribute('data-start'), 10) - 1);
		}

		env.element.appendChild(lineNumbersWrapper);

	});
	;
	(function () {

		if (!window.Prism) {
			return;
		}

		for (var language in Prism.languages) {
			var tokens = Prism.languages[language];

			tokens.tab = /\t/g;
			tokens.lf = /\n/g;
			tokens.cr = /\r/g;
		}

	})();
	;
	(function () {

		if (!self.Prism) {
			return;
		}

		var url = /\b([a-z]{3,7}:\/\/|tel:)[\w-+%~/.:#=?&amp;]+/,
			email = /\b\S+@[\w.]+[a-z]{2}/,
			linkMd = /\[([^\]]+)]\(([^)]+)\)/,

		// Tokens that may contain URLs and emails
			candidates = ['comment', 'url', 'attr-value', 'string'];

		for (var language in Prism.languages) {
			var tokens = Prism.languages[language];

			Prism.languages.DFS(tokens, function (type, def) {
				if (candidates.indexOf(type) > -1) {
					if (!def.pattern) {
						def = this[type] = {
							pattern: def
						};
					}

					def.inside = def.inside || {};

					if (type == 'comment') {
						def.inside['md-link'] = linkMd;
					}
					if (type == 'attr-value') {
						Prism.languages.insertBefore('inside', 'punctuation', {'url-link': url}, def);
					}
					else {
						def.inside['url-link'] = url;
					}

					def.inside['email-link'] = email;
				}
			});

			tokens['url-link'] = url;
			tokens['email-link'] = email;
		}

		Prism.hooks.add('wrap', function (env) {
			if (/-link$/.test(env.type)) {
				env.tag = 'a';

				var href = env.content;

				if (env.type == 'email-link' && href.indexOf('mailto:') != 0) {
					href = 'mailto:' + href;
				}
				else if (env.type == 'md-link') {
					// Markdown
					var match = env.content.match(linkMd);

					href = match[2];
					env.content = match[1];
				}

				env.attributes.href = href;
			}
		});

	})();
	;
	(function () {

		if (!self.Prism) {
			return;
		}

		if (Prism.languages.css) {
			Prism.languages.css.atrule.inside['atrule-id'] = /^@[\w-]+/;

			// check whether the selector is an advanced pattern before extending it
			if (Prism.languages.css.selector.pattern) {
				Prism.languages.css.selector.inside['pseudo-class'] = /:[\w-]+/;
				Prism.languages.css.selector.inside['pseudo-element'] = /::[\w-]+/;
			}
			else {
				Prism.languages.css.selector = {
					pattern: Prism.languages.css.selector,
					inside: {
						'pseudo-class': /:[\w-]+/,
						'pseudo-element': /::[\w-]+/
					}
				};
			}
		}

		if (Prism.languages.markup) {
			Prism.languages.markup.tag.inside.tag.inside['tag-id'] = /[\w-]+/;

			var Tags = {
				HTML: {
					'a': 1, 'abbr': 1, 'acronym': 1, 'b': 1, 'basefont': 1, 'bdo': 1, 'big': 1, 'blink': 1, 'cite': 1, 'code': 1, 'dfn': 1, 'em': 1, 'kbd': 1, 'i': 1,
					'rp': 1, 'rt': 1, 'ruby': 1, 's': 1, 'samp': 1, 'small': 1, 'spacer': 1, 'strike': 1, 'strong': 1, 'sub': 1, 'sup': 1, 'time': 1, 'tt': 1, 'u': 1,
					'var': 1, 'wbr': 1, 'noframes': 1, 'summary': 1, 'command': 1, 'dt': 1, 'dd': 1, 'figure': 1, 'figcaption': 1, 'center': 1, 'section': 1, 'nav': 1,
					'article': 1, 'aside': 1, 'hgroup': 1, 'header': 1, 'footer': 1, 'address': 1, 'noscript': 1, 'isIndex': 1, 'main': 1, 'mark': 1, 'marquee': 1,
					'meter': 1, 'menu': 1
				},
				SVG: {
					'animateColor': 1, 'animateMotion': 1, 'animateTransform': 1, 'glyph': 1, 'feBlend': 1, 'feColorMatrix': 1, 'feComponentTransfer': 1,
					'feFuncR': 1, 'feFuncG': 1, 'feFuncB': 1, 'feFuncA': 1, 'feComposite': 1, 'feConvolveMatrix': 1, 'feDiffuseLighting': 1, 'feDisplacementMap': 1,
					'feFlood': 1, 'feGaussianBlur': 1, 'feImage': 1, 'feMerge': 1, 'feMergeNode': 1, 'feMorphology': 1, 'feOffset': 1, 'feSpecularLighting': 1,
					'feTile': 1, 'feTurbulence': 1, 'feDistantLight': 1, 'fePointLight': 1, 'feSpotLight': 1, 'linearGradient': 1, 'radialGradient': 1, 'altGlyph': 1,
					'textPath': 1, 'tref': 1, 'altglyph': 1, 'textpath': 1, 'tref': 1, 'altglyphdef': 1, 'altglyphitem': 1, 'clipPath': 1, 'color-profile': 1, 'cursor': 1,
					'font-face': 1, 'font-face-format': 1, 'font-face-name': 1, 'font-face-src': 1, 'font-face-uri': 1, 'foreignObject': 1, 'glyph': 1, 'glyphRef': 1,
					'hkern': 1, 'vkern': 1,
				},
				MathML: {}
			}
		}

		var language;

		Prism.hooks.add('wrap', function (env) {
			if ((['tag-id'].indexOf(env.type) > -1
				|| (env.type == 'property' && env.content.indexOf('-') != 0)
				|| (env.type == 'atrule-id' && env.content.indexOf('@-') != 0)
				|| (env.type == 'pseudo-class' && env.content.indexOf(':-') != 0)
				|| (env.type == 'pseudo-element' && env.content.indexOf('::-') != 0)
				|| (env.type == 'attr-name' && env.content.indexOf('data-') != 0)
				) && env.content.indexOf('<') === -1
			) {
				var searchURL = 'w/index.php?fulltext&search=';

				env.tag = 'a';

				var href = 'http://docs.webplatform.org/';

				if (env.language == 'css') {
					href += 'wiki/css/'

					if (env.type == 'property') {
						href += 'properties/';
					}
					else if (env.type == 'atrule-id') {
						href += 'atrules/';
					}
					else if (env.type == 'pseudo-class') {
						href += 'selectors/pseudo-classes/';
					}
					else if (env.type == 'pseudo-element') {
						href += 'selectors/pseudo-elements/';
					}
				}
				else if (env.language == 'markup') {
					if (env.type == 'tag-id') {
						// Check language
						language = getLanguage(env.content) || language;

						if (language) {
							href += 'wiki/' + language + '/elements/';
						}
						else {
							href += searchURL;
						}
					}
					else if (env.type == 'attr-name') {
						if (language) {
							href += 'wiki/' + language + '/attributes/';
						}
						else {
							href += searchURL;
						}
					}
				}

				href += env.content;

				env.attributes.href = href;
				env.attributes.target = '_blank';
			}
		});

		function getLanguage(tag) {
			var tagL = tag.toLowerCase();

			if (Tags.HTML[tagL]) {
				return 'html';
			}
			else if (Tags.SVG[tag]) {
				return 'svg';
			}
			else if (Tags.MathML[tag]) {
				return 'mathml';
			}

			// Not in dictionary, perform check
			if (Tags.HTML[tagL] !== 0) {
				var htmlInterface = (document.createElement(tag).toString().match(/\[object HTML(.+)Element\]/) || [])[1];

				if (htmlInterface && htmlInterface != 'Unknown') {
					Tags.HTML[tagL] = 1;
					return 'html';
				}
			}

			Tags.HTML[tagL] = 0;

			if (Tags.SVG[tag] !== 0) {
				var svgInterface = (document.createElementNS('http://www.w3.org/2000/svg', tag).toString().match(/\[object SVG(.+)Element\]/) || [])[1];

				if (svgInterface && svgInterface != 'Unknown') {
					Tags.SVG[tag] = 1;
					return 'svg';
				}
			}

			Tags.SVG[tag] = 0;

			// Lame way to detect MathML, but browsers donâ€™t expose interface names there :(
			if (Tags.MathML[tag] !== 0) {
				if (tag.indexOf('m') === 0) {
					Tags.MathML[tag] = 1;
					return 'mathml';
				}
			}

			Tags.MathML[tag] = 0;

			return null;
		}

	})();
	;
	(function () {

		if (!self.Prism || !self.document || !document.querySelector) {
			return;
		}

		var Extensions = {
			'js': 'javascript',
			'html': 'markup',
			'svg': 'markup',
			'xml': 'markup',
			'py': 'python'
		};

		Array.prototype.slice.call(document.querySelectorAll('pre[data-src]')).forEach(function (pre) {
			var src = pre.getAttribute('data-src');
			var extension = (src.match(/\.(\w+)$/) || [, ''])[1];
			var language = Extensions[extension] || extension;

			var code = document.createElement('code');
			code.className = 'language-' + language;

			pre.textContent = '';

			code.textContent = 'Loadingâ€¦';

			pre.appendChild(code);

			var xhr = new XMLHttpRequest();

			xhr.open('GET', src, true);

			xhr.onreadystatechange = function () {
				if (xhr.readyState == 4) {

					if (xhr.status < 400 && xhr.responseText) {
						code.textContent = xhr.responseText;

						Prism.highlightElement(code);
					}
					else if (xhr.status >= 400) {
						code.textContent = 'âœ– Error ' + xhr.status + ' while fetching file: ' + xhr.statusText;
					}
					else {
						code.textContent = 'âœ– Error: File does not exist or is empty';
					}
				}
			};

			xhr.send(null);
		});

	})();
	;
	(function () {

		if (!self.Prism) {
			return;
		}

		var Languages = {
			'csharp': 'C#',
			'cpp': 'C++'
		};
		Prism.hooks.add('before-highlight', function (env) {
			var language = Languages[env.language] || env.language;
			env.element.setAttribute('data-language', language);
		});

	})();
	;
}