Test performance of Prism extension

Benchmark created by Andreas Rohner on


Description

This tests the performance of a new extension to Prism. It runs Prism on multiple versions of itself to get a big enough test sample.

Preparation HTML

<pre id="sampleCode" style="display: none;">
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));
                        } else if (_.util.type(tokens) === 'Array') {
                                return tokens.map(_.util.encode);
                        } else {
                                return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').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
                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;
                }

                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,
                                        check = pattern.checkMatch,
                                        checkState = {},
                                        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),
                                                lastIndex = 0;
                                        while(match && check) {
                                                if (check.call(checkState, match, lastIndex))
                                                        break;

                                                lastIndex = match.index;
                                                pattern.lastIndex = lastIndex + 1;
                                                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;
}


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));
                        } else if (_.util.type(tokens) === 'Array') {
                                return tokens.map(_.util.encode);
                        } else {
                                return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').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
                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;
                }

                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,
                                        check = pattern.checkMatch,
                                        checkState = {},
                                        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),
                                                lastIndex = 0;
                                        while(match && check) {
                                                if (check.call(checkState, match, lastIndex))
                                                        break;

                                                lastIndex = match.index;
                                                pattern.lastIndex = lastIndex + 1;
                                                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;
}


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));
                        } else if (_.util.type(tokens) === 'Array') {
                                return tokens.map(_.util.encode);
                        } else {
                                return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').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
                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;
                }

                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,
                                        check = pattern.checkMatch,
                                        checkState = {},
                                        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),
                                                lastIndex = 0;
                                        while(match && check) {
                                                if (check.call(checkState, match, lastIndex))
                                                        break;

                                                lastIndex = match.index;
                                                pattern.lastIndex = lastIndex + 1;
                                                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;
}


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));
                        } else if (_.util.type(tokens) === 'Array') {
                                return tokens.map(_.util.encode);
                        } else {
                                return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').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
                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;
                }

                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,
                                        check = pattern.checkMatch,
                                        checkState = {},
                                        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),
                                                lastIndex = 0;
                                        while(match && check) {
                                                if (check.call(checkState, match, lastIndex))
                                                        break;

                                                lastIndex = match.index;
                                                pattern.lastIndex = lastIndex + 1;
                                                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;
}


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));
                        } else if (_.util.type(tokens) === 'Array') {
                                return tokens.map(_.util.encode);
                        } else {
                                return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').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
                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;
                }

                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,
                                        check = pattern.checkMatch,
                                        checkState = {},
                                        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),
                                                lastIndex = 0;
                                        while(match && check) {
                                                if (check.call(checkState, match, lastIndex))
                                                        break;

                                                lastIndex = match.index;
                                                pattern.lastIndex = lastIndex + 1;
                                                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;
}


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));
                        } else if (_.util.type(tokens) === 'Array') {
                                return tokens.map(_.util.encode);
                        } else {
                                return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').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
                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;
                }

                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,
                                        check = pattern.checkMatch,
                                        checkState = {},
                                        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),
                                                lastIndex = 0;
                                        while(match && check) {
                                                if (check.call(checkState, match, lastIndex))
                                                        break;

                                                lastIndex = match.index;
                                                pattern.lastIndex = lastIndex + 1;
                                                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;
}


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));
                        } else if (_.util.type(tokens) === 'Array') {
                                return tokens.map(_.util.encode);
                        } else {
                                return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').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
                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;
                }

                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,
                                        check = pattern.checkMatch,
                                        checkState = {},
                                        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),
                                                lastIndex = 0;
                                        while(match && check) {
                                                if (check.call(checkState, match, lastIndex))
                                                        break;

                                                lastIndex = match.index;
                                                pattern.lastIndex = lastIndex + 1;
                                                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;
}

</pre>
<script>
self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{};var Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content)):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},clone:function(e){var n=t.util.type(e);switch(n){case"Object":var r={};for(var a in e)e.hasOwnProperty(a)&&(r[a]=t.util.clone(e[a]));return r;case"Array":return e.slice()}return e}},languages:{extend:function(e,n){var r=t.util.clone(t.languages[e]);for(var a in n)r[a]=n[a];return r},insertBefore:function(e,n,r,a){a=a||t.languages;var i=a[e],l={};for(var o in i)if(i.hasOwnProperty(o)){if(o==n)for(var s in r)r.hasOwnProperty(s)&&(l[s]=r[s]);l[o]=i[o]}return a[e]=l},DFS:function(e,n){for(var r in e)n.call(e,r,e[r]),"Object"===t.util.type(e)&&t.languages.DFS(e[r],n)}},highlightAll:function(e,n){for(var r,a=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'),i=0;r=a[i++];)t.highlightElement(r,e===!0,n)},highlightElement:function(r,a,i){for(var l,o,s=r;s&&!e.test(s.className);)s=s.parentNode;if(s&&(l=(s.className.match(e)||[,""])[1],o=t.languages[l]),o){r.className=r.className.replace(e,"").replace(/\s+/g," ")+" language-"+l,s=r.parentNode,/pre/i.test(s.nodeName)&&(s.className=s.className.replace(e,"").replace(/\s+/g," ")+" language-"+l);var c=r.textContent;if(c){var g={element:r,language:l,grammar:o,code:c};if(t.hooks.run("before-highlight",g),a&&self.Worker){var u=new Worker(t.filename);u.onmessage=function(e){g.highlightedCode=n.stringify(JSON.parse(e.data),l),t.hooks.run("before-insert",g),g.element.innerHTML=g.highlightedCode,i&&i.call(g.element),t.hooks.run("after-highlight",g)},u.postMessage(JSON.stringify({language:g.language,code:g.code}))}else g.highlightedCode=t.highlight(g.code,g.grammar,g.language),t.hooks.run("before-insert",g),g.element.innerHTML=g.highlightedCode,i&&i.call(r),t.hooks.run("after-highlight",g)}}},highlight:function(e,r,a){var i=t.tokenize(e,r);return n.stringify(t.util.encode(i),a)},tokenize:function(e,n){var r=t.Token,a=[e],i=n.rest;if(i){for(var l in i)n[l]=i[l];delete n.rest}e:for(var l in n)if(n.hasOwnProperty(l)&&n[l]){var o=n[l];o="Array"===t.util.type(o)?o:[o];for(var s=0;s<o.length;++s){var c=o[s],g=c.inside,u=c.checkMatch,f={},h=!!c.lookbehind,d=0;c=c.pattern||c;for(var p=0;p<a.length;p++){var m=a[p];if(a.length>e.length)break e;if(!(m instanceof r)){c.lastIndex=0;for(var v=c.exec(m),y=0;v&&u&&!u.call(f,v,y);)y=v.index,c.lastIndex=y+1,v=c.exec(m);if(v){h&&(d=v[1].length);var k=v.index-1+d,v=v[0].slice(d),b=v.length,w=k+b,N=m.slice(0,k+1),O=m.slice(w+1),S=[p,1];N&&S.push(N);var x=new r(l,g?t.tokenize(v,g):v);S.push(x),O&&S.push(O),Array.prototype.splice.apply(a,S)}}}}}return a},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[],r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(r&&r.length)for(var a,i=0;a=r[i++];)a(n)}}},n=t.Token=function(e,t){this.type=e,this.content=t};if(n.stringify=function(e,r,a){if("string"==typeof e)return e;if("[object Array]"==Object.prototype.toString.call(e))return e.map(function(t){return n.stringify(t,r,e)}).join("");var i={type:e.type,content:n.stringify(e.content,r,a),tag:"span",classes:["token",e.type],attributes:{},language:r,parent:a};"comment"==i.type&&(i.attributes.spellcheck="true"),t.hooks.run("wrap",i);var l="";for(var o in i.attributes)l+=o+'="'+(i.attributes[o]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+l+">"+i.content+"</"+i.tag+">"},!self.document)return self.addEventListener?(self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,a=n.code;self.postMessage(JSON.stringify(t.tokenize(a,t.languages[r]))),self.close()},!1),self.Prism):self.Prism;var r=document.getElementsByTagName("script");return r=r[r.length-1],r&&(t.filename=r.src,document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism);

var extendedPrism = Prism;
Prism = null;

self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{};var Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content)):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},clone:function(e){var n=t.util.type(e);switch(n){case"Object":var r={};for(var a in e)e.hasOwnProperty(a)&&(r[a]=t.util.clone(e[a]));return r;case"Array":return e.slice()}return e}},languages:{extend:function(e,n){var r=t.util.clone(t.languages[e]);for(var a in n)r[a]=n[a];return r},insertBefore:function(e,n,r,a){a=a||t.languages;var i=a[e],o={};for(var l in i)if(i.hasOwnProperty(l)){if(l==n)for(var s in r)r.hasOwnProperty(s)&&(o[s]=r[s]);o[l]=i[l]}return a[e]=o},DFS:function(e,n){for(var r in e)n.call(e,r,e[r]),"Object"===t.util.type(e)&&t.languages.DFS(e[r],n)}},highlightAll:function(e,n){for(var r,a=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'),i=0;r=a[i++];)t.highlightElement(r,e===!0,n)},highlightElement:function(r,a,i){for(var o,l,s=r;s&&!e.test(s.className);)s=s.parentNode;if(s&&(o=(s.className.match(e)||[,""])[1],l=t.languages[o]),l){r.className=r.className.replace(e,"").replace(/\s+/g," ")+" language-"+o,s=r.parentNode,/pre/i.test(s.nodeName)&&(s.className=s.className.replace(e,"").replace(/\s+/g," ")+" language-"+o);var c=r.textContent;if(c){var g={element:r,language:o,grammar:l,code:c};if(t.hooks.run("before-highlight",g),a&&self.Worker){var u=new Worker(t.filename);u.onmessage=function(e){g.highlightedCode=n.stringify(JSON.parse(e.data),o),t.hooks.run("before-insert",g),g.element.innerHTML=g.highlightedCode,i&&i.call(g.element),t.hooks.run("after-highlight",g)},u.postMessage(JSON.stringify({language:g.language,code:g.code}))}else g.highlightedCode=t.highlight(g.code,g.grammar,g.language),t.hooks.run("before-insert",g),g.element.innerHTML=g.highlightedCode,i&&i.call(r),t.hooks.run("after-highlight",g)}}},highlight:function(e,r,a){var i=t.tokenize(e,r);return n.stringify(t.util.encode(i),a)},tokenize:function(e,n){var r=t.Token,a=[e],i=n.rest;if(i){for(var o in i)n[o]=i[o];delete n.rest}e:for(var o in n)if(n.hasOwnProperty(o)&&n[o]){var l=n[o];l="Array"===t.util.type(l)?l:[l];for(var s=0;s<l.length;++s){var c=l[s],g=c.inside,u=!!c.lookbehind,f=0;c=c.pattern||c;for(var h=0;h<a.length;h++){var d=a[h];if(a.length>e.length)break e;if(!(d instanceof r)){c.lastIndex=0;var p=c.exec(d);if(p){u&&(f=p[1].length);var m=p.index-1+f,p=p[0].slice(f),v=p.length,y=m+v,k=d.slice(0,m+1),b=d.slice(y+1),w=[h,1];k&&w.push(k);var N=new r(o,g?t.tokenize(p,g):p);w.push(N),b&&w.push(b),Array.prototype.splice.apply(a,w)}}}}}return a},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[],r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(r&&r.length)for(var a,i=0;a=r[i++];)a(n)}}},n=t.Token=function(e,t){this.type=e,this.content=t};if(n.stringify=function(e,r,a){if("string"==typeof e)return e;if("[object Array]"==Object.prototype.toString.call(e))return e.map(function(t){return n.stringify(t,r,e)}).join("");var i={type:e.type,content:n.stringify(e.content,r,a),tag:"span",classes:["token",e.type],attributes:{},language:r,parent:a};"comment"==i.type&&(i.attributes.spellcheck="true"),t.hooks.run("wrap",i);var o="";for(var l in i.attributes)o+=l+'="'+(i.attributes[l]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+o+">"+i.content+"</"+i.tag+">"},!self.document)return self.addEventListener?(self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,a=n.code;self.postMessage(JSON.stringify(t.tokenize(a,t.languages[r]))),self.close()},!1),self.Prism):self.Prism;var r=document.getElementsByTagName("script");return r=r[r.length-1],r&&(t.filename=r.src,document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism);

var normalPrism = Prism;

Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//g,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*?(\r?\n|$)/g,lookbehind:!0}],string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/gi,lookbehind:!0,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_]+\(/gi,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.javascript=Prism.languages.extend("clike",{keyword:/\b(break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|get|if|implements|import|in|instanceof|interface|let|new|null|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\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:!0}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/[\w\W]*?<\/script>/gi,inside:{tag:{pattern:/|<\/script>/gi,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});;

var normalClike=Prism.languages.clike;
var normalJS=Prism.languages.javascript;

Prism.languages.clike = null;
Prism.languages.javascript = null;

Prism.languages.clike={comment:{pattern:/\/\*[\w\W]*?\*\/|\/\/.*/g,checkMatch:function(e,t){for(var n=!!this.inDoubleQuote,i=!!this.inSingleQuote,a=!!this.inRegex,s=!!this.isEscaped,c=t||0,o=e.input,r=e.index;r>c;++c)switch(o.charCodeAt(c)){case 34:n=!(n&&!s||i||a);break;case 39:i=!(n||i&&!s||a);break;case 47:a=!(n||i||a&&!s);break;case 10:a=!1;break;case 92:s=!s;break;default:s=!1}return this.inDoubleQuote=n,this.inSingleQuote=i,this.inRegex=a,this.isEscaped=s,!n&&!i&&!a}},string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/gi,lookbehind:!0,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_]+\(/gi,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.javascript=Prism.languages.extend("clike",{keyword:/\b(break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|get|if|implements|import|in|instanceof|interface|let|new|null|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\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:!0}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/<script[\w\W]*?>[\w\W]*?<\/script>/gi,inside:{tag:{pattern:/<script[\w\W]*?>|<\/script>/gi,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});

var extendedClike=Prism.languages.clike;
var extendedJS=Prism.languages.javascript;

Prism.languages.clike = null;
Prism.languages.javascript = null;

var sampleCode = document.getElementById("sampleCode").textContent;

for (var i = 0; i < 10; ++i) {
    Prism = normalPrism;
    Prism.languages.clike = normalClike;
    Prism.languages.javascript = normalJS;

    Prism.tokenize(sampleCode, Prism.languages.javascript, "javascript");

    Prism = extendedPrism;
    Prism.languages.clike = extendedClike;
    Prism.languages.javascript = extendedJS;

    Prism.tokenize(sampleCode, Prism.languages.javascript, "javascript");
}

Prism.languages.clike = null;
Prism.languages.javascript = null;
Prism = null;
</script>

Teardown


    Prism.languages.clike = null;
    Prism.languages.javascript = null;
    Prism = null;
  

Test runner

Ready to run.

Testing in
TestOps/sec
Normal Prism
Prism = normalPrism;
Prism.languages.clike = normalClike;
Prism.languages.javascript = normalJS;

Prism.tokenize(sampleCode, Prism.languages.javascript, "javascript");
ready
Enhanced Prism
Prism = extendedPrism;
Prism.languages.clike = extendedClike;
Prism.languages.javascript = extendedJS;

Prism.tokenize(sampleCode, Prism.languages.javascript, "javascript");
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.

  • Revision 1: published by Andreas Rohner on