[devdocsgjs/main: 1033/1867] Update Prism to 1.19, add shellsession language




commit 7d04a3080d30fadbb63806f793de9e92c7b14d15
Author: Jed Fox <git twopointzero us>
Date:   Wed Jan 29 15:41:43 2020 -0500

    Update Prism to 1.19, add shellsession language

 assets/javascripts/vendor/prism.js | 2291 +++++++++++++++++++-----------------
 1 file changed, 1220 insertions(+), 1071 deletions(-)
---
diff --git a/assets/javascripts/vendor/prism.js b/assets/javascripts/vendor/prism.js
index a01a207c..86fbb074 100644
--- a/assets/javascripts/vendor/prism.js
+++ b/assets/javascripts/vendor/prism.js
@@ -1,11 +1,11 @@
-/* PrismJS 1.17.1
-https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+c+bash+cpp+coffeescript+ruby+d+dart+markup-templating+elixir+erlang+go+groovy+java+php+json+julia+kotlin+crystal+lua+django+matlab+typescript+nginx+nim+perl+sql+scss+python+jsx+rust+yaml
 */
+/* PrismJS 1.19.0
+https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+c+cpp+coffeescript+crystal+d+dart+django+elixir+erlang+go+groovy+java+json+julia+kotlin+lua+markup-templating+matlab+nginx+nim+perl+php+python+jsx+ruby+rust+scss+shell-session+sql+typescript+yaml
 */
 var _self = (typeof window !== 'undefined')
   ? window   // if in browser
   : (
     (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope)
-      ? self // if in worker
-      : {}   // if in node js
+    ? self // if in worker
+    : {}   // if in node js
   );
 
 /**
@@ -17,529 +17,599 @@ var _self = (typeof window !== 'undefined')
 var Prism = (function (_self){
 
 // Private helper vars
-  var lang = /\blang(?:uage)?-([\w-]+)\b/i;
-  var uniqueId = 0;
-
-  var _ = {
-    manual: _self.Prism && _self.Prism.manual,
-    disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler,
-    util: {
-      encode: function (tokens) {
-        if (tokens instanceof Token) {
-          return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias);
-        } else if (Array.isArray(tokens)) {
-          return tokens.map(_.util.encode);
-        } else {
-          return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' ');
-        }
-      },
+var lang = /\blang(?:uage)?-([\w-]+)\b/i;
+var uniqueId = 0;
+
+
+var _ = {
+  manual: _self.Prism && _self.Prism.manual,
+  disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler,
+  util: {
+    encode: function (tokens) {
+      if (tokens instanceof Token) {
+        return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias);
+      } else if (Array.isArray(tokens)) {
+        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).slice(8, -1);
-      },
+    type: function (o) {
+      return Object.prototype.toString.call(o).slice(8, -1);
+    },
 
-      objId: function (obj) {
-        if (!obj['__id']) {
-          Object.defineProperty(obj, '__id', { value: ++uniqueId });
-        }
-        return obj['__id'];
-      },
+    objId: function (obj) {
+      if (!obj['__id']) {
+        Object.defineProperty(obj, '__id', { value: ++uniqueId });
+      }
+      return obj['__id'];
+    },
 
-      // Deep clone a language definition (e.g. to extend it)
-      clone: function deepClone(o, visited) {
-        var clone, id, type = _.util.type(o);
-        visited = visited || {};
+    // Deep clone a language definition (e.g. to extend it)
+    clone: function deepClone(o, visited) {
+      var clone, id, type = _.util.type(o);
+      visited = visited || {};
 
-        switch (type) {
-          case 'Object':
-            id = _.util.objId(o);
-            if (visited[id]) {
-              return visited[id];
-            }
-            clone = {};
-            visited[id] = clone;
+      switch (type) {
+        case 'Object':
+          id = _.util.objId(o);
+          if (visited[id]) {
+            return visited[id];
+          }
+          clone = {};
+          visited[id] = clone;
 
-            for (var key in o) {
-              if (o.hasOwnProperty(key)) {
-                clone[key] = deepClone(o[key], visited);
-              }
+          for (var key in o) {
+            if (o.hasOwnProperty(key)) {
+              clone[key] = deepClone(o[key], visited);
             }
+          }
 
-            return clone;
+          return clone;
 
-          case 'Array':
-            id = _.util.objId(o);
-            if (visited[id]) {
-              return visited[id];
-            }
-            clone = [];
-            visited[id] = clone;
+        case 'Array':
+          id = _.util.objId(o);
+          if (visited[id]) {
+            return visited[id];
+          }
+          clone = [];
+          visited[id] = clone;
 
-            o.forEach(function (v, i) {
-              clone[i] = deepClone(v, visited);
-            });
+          o.forEach(function (v, i) {
+            clone[i] = deepClone(v, visited);
+          });
 
-            return clone;
+          return clone;
 
-          default:
-            return o;
-        }
+        default:
+          return o;
       }
     },
 
-    languages: {
-      extend: function (id, redef) {
-        var lang = _.util.clone(_.languages[id]);
+    /**
+     * Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class.
+     *
+     * If no language is set for the element or the element is `null` or `undefined`, `none` will be 
returned.
+     *
+     * @param {Element} element
+     * @returns {string}
+     */
+    getLanguage: function (element) {
+      while (element && !lang.test(element.className)) {
+        element = element.parentElement;
+      }
+      if (element) {
+        return (element.className.match(lang) || [, 'none'])[1].toLowerCase();
+      }
+      return 'none';
+    },
+
+    /**
+     * Returns the script element that is currently executing.
+     *
+     * This does __not__ work for line script element.
+     *
+     * @returns {HTMLScriptElement | null}
+     */
+    currentScript: function () {
+      if (typeof document === 'undefined') {
+        return null;
+      }
+      if ('currentScript' in document) {
+        return document.currentScript;
+      }
 
-        for (var key in redef) {
-          lang[key] = redef[key];
+      // IE11 workaround
+      // we'll get the src of the current script by parsing IE11's error stack trace
+      // this will not work for inline scripts
+
+      try {
+        throw new Error();
+      } catch (err) {
+        // Get file src url from stack. Specifically works with the format of stack traces in IE.
+        // A stack will look like this:
+        //
+        // Error
+        //    at _.util.currentScript (http://localhost/components/prism-core.js:119:5)
+        //    at Global code (http://localhost/components/prism-core.js:606:1)
+
+        var src = (/at [^(\r\n]*\((.*):.+:.+\)$/i.exec(err.stack) || [])[1];
+        if (src) {
+          var scripts = document.getElementsByTagName('script');
+          for (var i in scripts) {
+            if (scripts[i].src == src) {
+              return scripts[i];
+            }
+          }
         }
+        return null;
+      }
+    }
+  },
 
-        return lang;
-      },
+  languages: {
+    extend: function (id, redef) {
+      var lang = _.util.clone(_.languages[id]);
 
-      /**
-       * Insert a token before another token in a language literal
-       * As this needs to recreate the object (we cannot actually insert before keys in object literals),
-       * we cannot just provide an object, we need an object and a key.
-       * @param inside The key (or language id) of the parent
-       * @param before The key to insert before.
-       * @param insert Object with the key/value pairs to insert
-       * @param root The object that contains `inside`. If equal to Prism.languages, it can be omitted.
-       */
-      insertBefore: function (inside, before, insert, root) {
-        root = root || _.languages;
-        var grammar = root[inside];
-        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];
-                }
+      for (var key in redef) {
+        lang[key] = redef[key];
+      }
+
+      return lang;
+    },
+
+    /**
+     * Insert a token before another token in a language literal
+     * As this needs to recreate the object (we cannot actually insert before keys in object literals),
+     * we cannot just provide an object, we need an object and a key.
+     * @param inside The key (or language id) of the parent
+     * @param before The key to insert before.
+     * @param insert Object with the key/value pairs to insert
+     * @param root The object that contains `inside`. If equal to Prism.languages, it can be omitted.
+     */
+    insertBefore: function (inside, before, insert, root) {
+      root = root || _.languages;
+      var grammar = root[inside];
+      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];
               }
             }
+          }
 
-            // Do not insert token which also occur in insert. See #1525
-            if (!insert.hasOwnProperty(token)) {
-              ret[token] = grammar[token];
-            }
+          // Do not insert token which also occur in insert. See #1525
+          if (!insert.hasOwnProperty(token)) {
+            ret[token] = grammar[token];
           }
         }
+      }
 
-        var old = root[inside];
-        root[inside] = ret;
+      var old = root[inside];
+      root[inside] = ret;
 
-        // Update references in other language definitions
-        _.languages.DFS(_.languages, function(key, value) {
-          if (value === old && key != inside) {
-            this[key] = ret;
-          }
-        });
+      // Update references in other language definitions
+      _.languages.DFS(_.languages, function(key, value) {
+        if (value === old && key != inside) {
+          this[key] = ret;
+        }
+      });
 
-        return ret;
-      },
+      return ret;
+    },
 
-      // Traverse a language definition with Depth First Search
-      DFS: function DFS(o, callback, type, visited) {
-        visited = visited || {};
+    // Traverse a language definition with Depth First Search
+    DFS: function DFS(o, callback, type, visited) {
+      visited = visited || {};
 
-        var objId = _.util.objId;
+      var objId = _.util.objId;
 
-        for (var i in o) {
-          if (o.hasOwnProperty(i)) {
-            callback.call(o, i, o[i], type || i);
+      for (var i in o) {
+        if (o.hasOwnProperty(i)) {
+          callback.call(o, i, o[i], type || i);
 
-            var property = o[i],
+          var property = o[i],
               propertyType = _.util.type(property);
 
-            if (propertyType === 'Object' && !visited[objId(property)]) {
-              visited[objId(property)] = true;
-              DFS(property, callback, null, visited);
-            }
-            else if (propertyType === 'Array' && !visited[objId(property)]) {
-              visited[objId(property)] = true;
-              DFS(property, callback, i, visited);
-            }
+          if (propertyType === 'Object' && !visited[objId(property)]) {
+            visited[objId(property)] = true;
+            DFS(property, callback, null, visited);
+          }
+          else if (propertyType === 'Array' && !visited[objId(property)]) {
+            visited[objId(property)] = true;
+            DFS(property, callback, i, visited);
           }
         }
       }
-    },
-    plugins: {},
+    }
+  },
+  plugins: {},
 
-    highlightAll: function(async, callback) {
-      _.highlightAllUnder(document, async, callback);
-    },
+  highlightAll: function(async, callback) {
+    _.highlightAllUnder(document, async, callback);
+  },
 
-    highlightAllUnder: function(container, async, callback) {
-      var env = {
-        callback: callback,
-        selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], 
[class*="lang-"] code'
-      };
+  highlightAllUnder: function(container, async, callback) {
+    var env = {
+      callback: callback,
+      container: container,
+      selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] 
code'
+    };
 
-      _.hooks.run('before-highlightall', env);
+    _.hooks.run('before-highlightall', env);
 
-      var elements = container.querySelectorAll(env.selector);
+    env.elements = Array.prototype.slice.apply(env.container.querySelectorAll(env.selector));
 
-      for (var i=0, element; element = elements[i++];) {
-        _.highlightElement(element, async === true, env.callback);
-      }
-    },
+    _.hooks.run('before-all-elements-highlight', env);
 
-    highlightElement: function(element, async, callback) {
-      // Find language
-      var language = 'none', grammar, parent = element;
+    for (var i = 0, element; element = env.elements[i++];) {
+      _.highlightElement(element, async === true, env.callback);
+    }
+  },
 
-      while (parent && !lang.test(parent.className)) {
-        parent = parent.parentNode;
-      }
+  highlightElement: function(element, async, callback) {
+    // Find language
+    var language = _.util.getLanguage(element);
+    var grammar = _.languages[language];
 
-      if (parent) {
-        language = (parent.className.match(lang) || [,'none'])[1].toLowerCase();
-        grammar = _.languages[language];
-      }
+    // Set language on the element, if not present
+    element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
 
-      // 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
+    var parent = element.parentNode;
+    if (parent && parent.nodeName.toLowerCase() === 'pre') {
+      parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
+    }
 
-      if (element.parentNode) {
-        // Set language on the parent, for styling
-        parent = element.parentNode;
+    var code = element.textContent;
 
-        if (/pre/i.test(parent.nodeName)) {
-          parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + 
language;
-        }
-      }
+    var env = {
+      element: element,
+      language: language,
+      grammar: grammar,
+      code: code
+    };
 
-      var code = element.textContent;
+    function insertHighlightedCode(highlightedCode) {
+      env.highlightedCode = highlightedCode;
 
-      var env = {
-        element: element,
-        language: language,
-        grammar: grammar,
-        code: code
-      };
+      _.hooks.run('before-insert', env);
 
-      var insertHighlightedCode = function (highlightedCode) {
-        env.highlightedCode = highlightedCode;
+      env.element.innerHTML = env.highlightedCode;
 
-        _.hooks.run('before-insert', env);
+      _.hooks.run('after-highlight', env);
+      _.hooks.run('complete', env);
+      callback && callback.call(env.element);
+    }
 
-        env.element.innerHTML = env.highlightedCode;
+    _.hooks.run('before-sanity-check', env);
 
-        _.hooks.run('after-highlight', env);
-        _.hooks.run('complete', env);
-        callback && callback.call(env.element);
-      }
+    if (!env.code) {
+      _.hooks.run('complete', env);
+      callback && callback.call(env.element);
+      return;
+    }
 
-      _.hooks.run('before-sanity-check', env);
+    _.hooks.run('before-highlight', env);
 
-      if (!env.code) {
-        _.hooks.run('complete', env);
-        return;
-      }
+    if (!env.grammar) {
+      insertHighlightedCode(_.util.encode(env.code));
+      return;
+    }
 
-      _.hooks.run('before-highlight', env);
+    if (async && _self.Worker) {
+      var worker = new Worker(_.filename);
 
-      if (!env.grammar) {
-        insertHighlightedCode(_.util.encode(env.code));
-        return;
-      }
+      worker.onmessage = function(evt) {
+        insertHighlightedCode(evt.data);
+      };
 
-      if (async && _self.Worker) {
-        var worker = new Worker(_.filename);
+      worker.postMessage(JSON.stringify({
+        language: env.language,
+        code: env.code,
+        immediateClose: true
+      }));
+    }
+    else {
+      insertHighlightedCode(_.highlight(env.code, env.grammar, env.language));
+    }
+  },
 
-        worker.onmessage = function(evt) {
-          insertHighlightedCode(evt.data);
-        };
+  highlight: function (text, grammar, language) {
+    var env = {
+      code: text,
+      grammar: grammar,
+      language: language
+    };
+    _.hooks.run('before-tokenize', env);
+    env.tokens = _.tokenize(env.code, env.grammar);
+    _.hooks.run('after-tokenize', env);
+    return Token.stringify(_.util.encode(env.tokens), env.language);
+  },
 
-        worker.postMessage(JSON.stringify({
-          language: env.language,
-          code: env.code,
-          immediateClose: true
-        }));
-      }
-      else {
-        insertHighlightedCode(_.highlight(env.code, env.grammar, env.language));
+  matchGrammar: function (text, strarr, grammar, index, startPos, oneshot, target) {
+    for (var token in grammar) {
+      if (!grammar.hasOwnProperty(token) || !grammar[token]) {
+        continue;
       }
-    },
 
-    highlight: function (text, grammar, language) {
-      var env = {
-        code: text,
-        grammar: grammar,
-        language: language
-      };
-      _.hooks.run('before-tokenize', env);
-      env.tokens = _.tokenize(env.code, env.grammar);
-      _.hooks.run('after-tokenize', env);
-      return Token.stringify(_.util.encode(env.tokens), env.language);
-    },
+      var patterns = grammar[token];
+      patterns = Array.isArray(patterns) ? patterns : [patterns];
 
-    matchGrammar: function (text, strarr, grammar, index, startPos, oneshot, target) {
-      for (var token in grammar) {
-        if(!grammar.hasOwnProperty(token) || !grammar[token]) {
-          continue;
+      for (var j = 0; j < patterns.length; ++j) {
+        if (target && target == token + ',' + j) {
+          return;
         }
 
-        if (token == target) {
-          return;
+        var pattern = patterns[j],
+          inside = pattern.inside,
+          lookbehind = !!pattern.lookbehind,
+          greedy = !!pattern.greedy,
+          lookbehindLength = 0,
+          alias = pattern.alias;
+
+        if (greedy && !pattern.pattern.global) {
+          // Without the global flag, lastIndex won't work
+          var flags = pattern.pattern.toString().match(/[imsuy]*$/)[0];
+          pattern.pattern = RegExp(pattern.pattern.source, flags + 'g');
         }
 
-        var patterns = grammar[token];
-        patterns = (_.util.type(patterns) === "Array") ? patterns : [patterns];
-
-        for (var j = 0; j < patterns.length; ++j) {
-          var pattern = patterns[j],
-            inside = pattern.inside,
-            lookbehind = !!pattern.lookbehind,
-            greedy = !!pattern.greedy,
-            lookbehindLength = 0,
-            alias = pattern.alias;
-
-          if (greedy && !pattern.pattern.global) {
-            // Without the global flag, lastIndex won't work
-            var flags = pattern.pattern.toString().match(/[imuy]*$/)[0];
-            pattern.pattern = RegExp(pattern.pattern.source, flags + "g");
-          }
+        pattern = pattern.pattern || pattern;
 
-          pattern = pattern.pattern || pattern;
+        // Don’t cache length as it changes during the loop
+        for (var i = index, pos = startPos; i < strarr.length; pos += strarr[i].length, ++i) {
 
-          // Don’t cache length as it changes during the loop
-          for (var i = index, pos = startPos; i < strarr.length; pos += strarr[i].length, ++i) {
+          var str = strarr[i];
 
-            var str = strarr[i];
+          if (strarr.length > text.length) {
+            // Something went terribly wrong, ABORT, ABORT!
+            return;
+          }
 
-            if (strarr.length > text.length) {
-              // Something went terribly wrong, ABORT, ABORT!
-              return;
-            }
+          if (str instanceof Token) {
+            continue;
+          }
 
-            if (str instanceof Token) {
-              continue;
+          if (greedy && i != strarr.length - 1) {
+            pattern.lastIndex = pos;
+            var match = pattern.exec(text);
+            if (!match) {
+              break;
             }
 
-            if (greedy && i != strarr.length - 1) {
-              pattern.lastIndex = pos;
-              var match = pattern.exec(text);
-              if (!match) {
-                break;
-              }
-
-              var from = match.index + (lookbehind ? match[1].length : 0),
+            var from = match.index + (lookbehind && match[1] ? match[1].length : 0),
                 to = match.index + match[0].length,
                 k = i,
                 p = pos;
 
-              for (var len = strarr.length; k < len && (p < to || (!strarr[k].type && !strarr[k - 
1].greedy)); ++k) {
-                p += strarr[k].length;
-                // Move the index i to the element in strarr that is closest to from
-                if (from >= p) {
-                  ++i;
-                  pos = p;
-                }
-              }
-
-              // If strarr[i] is a Token, then the match starts inside another Token, which is invalid
-              if (strarr[i] instanceof Token) {
-                continue;
+            for (var len = strarr.length; k < len && (p < to || (!strarr[k].type && !strarr[k - 1].greedy)); 
++k) {
+              p += strarr[k].length;
+              // Move the index i to the element in strarr that is closest to from
+              if (from >= p) {
+                ++i;
+                pos = p;
               }
-
-              // Number of tokens to delete and replace with the new match
-              delNum = k - i;
-              str = text.slice(pos, p);
-              match.index -= pos;
-            } else {
-              pattern.lastIndex = 0;
-
-              var match = pattern.exec(str),
-                delNum = 1;
             }
 
-            if (!match) {
-              if (oneshot) {
-                break;
-              }
-
+            // If strarr[i] is a Token, then the match starts inside another Token, which is invalid
+            if (strarr[i] instanceof Token) {
               continue;
             }
 
-            if(lookbehind) {
-              lookbehindLength = match[1] ? match[1].length : 0;
+            // Number of tokens to delete and replace with the new match
+            delNum = k - i;
+            str = text.slice(pos, p);
+            match.index -= pos;
+          } else {
+            pattern.lastIndex = 0;
+
+            var match = pattern.exec(str),
+              delNum = 1;
+          }
+
+          if (!match) {
+            if (oneshot) {
+              break;
             }
 
-            var from = match.index + lookbehindLength,
+            continue;
+          }
+
+          if(lookbehind) {
+            lookbehindLength = match[1] ? match[1].length : 0;
+          }
+
+          var from = match.index + lookbehindLength,
               match = match[0].slice(lookbehindLength),
               to = from + match.length,
               before = str.slice(0, from),
               after = str.slice(to);
 
-            var args = [i, delNum];
+          var args = [i, delNum];
 
-            if (before) {
-              ++i;
-              pos += before.length;
-              args.push(before);
-            }
+          if (before) {
+            ++i;
+            pos += before.length;
+            args.push(before);
+          }
 
-            var wrapped = new Token(token, inside? _.tokenize(match, inside) : match, alias, match, greedy);
+          var wrapped = new Token(token, inside? _.tokenize(match, inside) : match, alias, match, greedy);
 
-            args.push(wrapped);
+          args.push(wrapped);
 
-            if (after) {
-              args.push(after);
-            }
+          if (after) {
+            args.push(after);
+          }
 
-            Array.prototype.splice.apply(strarr, args);
+          Array.prototype.splice.apply(strarr, args);
 
-            if (delNum != 1)
-              _.matchGrammar(text, strarr, grammar, i, pos, true, token);
+          if (delNum != 1)
+            _.matchGrammar(text, strarr, grammar, i, pos, true, token + ',' + j);
 
-            if (oneshot)
-              break;
-          }
+          if (oneshot)
+            break;
         }
       }
-    },
-
-    tokenize: function(text, grammar) {
-      var strarr = [text];
+    }
+  },
 
-      var rest = grammar.rest;
+  tokenize: function(text, grammar) {
+    var strarr = [text];
 
-      if (rest) {
-        for (var token in rest) {
-          grammar[token] = rest[token];
-        }
+    var rest = grammar.rest;
 
-        delete grammar.rest;
+    if (rest) {
+      for (var token in rest) {
+        grammar[token] = rest[token];
       }
 
-      _.matchGrammar(text, strarr, grammar, 0, 0, false);
-
-      return strarr;
-    },
-
-    hooks: {
-      all: {},
+      delete grammar.rest;
+    }
 
-      add: function (name, callback) {
-        var hooks = _.hooks.all;
+    _.matchGrammar(text, strarr, grammar, 0, 0, false);
 
-        hooks[name] = hooks[name] || [];
+    return strarr;
+  },
 
-        hooks[name].push(callback);
-      },
+  hooks: {
+    all: {},
 
-      run: function (name, env) {
-        var callbacks = _.hooks.all[name];
+    add: function (name, callback) {
+      var hooks = _.hooks.all;
 
-        if (!callbacks || !callbacks.length) {
-          return;
-        }
+      hooks[name] = hooks[name] || [];
 
-        for (var i=0, callback; callback = callbacks[i++];) {
-          callback(env);
-        }
-      }
+      hooks[name].push(callback);
     },
 
-    Token: Token
-  };
-
-  _self.Prism = _;
+    run: function (name, env) {
+      var callbacks = _.hooks.all[name];
 
-  function Token(type, content, alias, matchedStr, greedy) {
-    this.type = type;
-    this.content = content;
-    this.alias = alias;
-    // Copy of the full string this token was created from
-    this.length = (matchedStr || "").length|0;
-    this.greedy = !!greedy;
-  }
+      if (!callbacks || !callbacks.length) {
+        return;
+      }
 
-  Token.stringify = function(o, language) {
-    if (typeof o == 'string') {
-      return o;
+      for (var i=0, callback; callback = callbacks[i++];) {
+        callback(env);
+      }
     }
+  },
 
-    if (Array.isArray(o)) {
-      return o.map(function(element) {
-        return Token.stringify(element, language);
-      }).join('');
-    }
+  Token: Token
+};
 
-    var env = {
-      type: o.type,
-      content: Token.stringify(o.content, language),
-      tag: 'span',
-      classes: ['token', o.type],
-      attributes: {},
-      language: language
-    };
+_self.Prism = _;
 
-    if (o.alias) {
-      var aliases = Array.isArray(o.alias) ? o.alias : [o.alias];
-      Array.prototype.push.apply(env.classes, aliases);
-    }
+function Token(type, content, alias, matchedStr, greedy) {
+  this.type = type;
+  this.content = content;
+  this.alias = alias;
+  // Copy of the full string this token was created from
+  this.length = (matchedStr || '').length|0;
+  this.greedy = !!greedy;
+}
 
-    _.hooks.run('wrap', env);
+Token.stringify = function(o, language) {
+  if (typeof o == 'string') {
+    return o;
+  }
 
-    var attributes = Object.keys(env.attributes).map(function(name) {
-      return name + '="' + (env.attributes[name] || '').replace(/"/g, '&quot;') + '"';
-    }).join(' ');
+  if (Array.isArray(o)) {
+    return o.map(function(element) {
+      return Token.stringify(element, language);
+    }).join('');
+  }
 
-    return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + (attributes ? ' ' + attributes : '') + 
'>' + env.content + '</' + env.tag + '>';
+  var env = {
+    type: o.type,
+    content: Token.stringify(o.content, language),
+    tag: 'span',
+    classes: ['token', o.type],
+    attributes: {},
+    language: language
   };
 
-  if (!_self.document) {
-    if (!_self.addEventListener) {
-      // in Node.js
-      return _;
-    }
+  if (o.alias) {
+    var aliases = Array.isArray(o.alias) ? o.alias : [o.alias];
+    Array.prototype.push.apply(env.classes, aliases);
+  }
 
-    if (!_.disableWorkerMessageHandler) {
-      // In worker
-      _self.addEventListener('message', function (evt) {
-        var message = JSON.parse(evt.data),
-          lang = message.language,
-          code = message.code,
-          immediateClose = message.immediateClose;
+  _.hooks.run('wrap', env);
 
-        _self.postMessage(_.highlight(code, _.languages[lang], lang));
-        if (immediateClose) {
-          _self.close();
-        }
-      }, false);
-    }
+  var attributes = Object.keys(env.attributes).map(function(name) {
+    return name + '="' + (env.attributes[name] || '').replace(/"/g, '&quot;') + '"';
+  }).join(' ');
 
+  return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + (attributes ? ' ' + attributes : '') + 
'>' + env.content + '</' + env.tag + '>';
+};
+
+if (!_self.document) {
+  if (!_self.addEventListener) {
+    // in Node.js
     return _;
   }
 
+  if (!_.disableWorkerMessageHandler) {
+    // In worker
+    _self.addEventListener('message', function (evt) {
+      var message = JSON.parse(evt.data),
+        lang = message.language,
+        code = message.code,
+        immediateClose = message.immediateClose;
+
+      _self.postMessage(_.highlight(code, _.languages[lang], lang));
+      if (immediateClose) {
+        _self.close();
+      }
+    }, false);
+  }
+
+  return _;
+}
+
 //Get current script and highlight
-  var script = document.currentScript || [].slice.call(document.getElementsByTagName("script")).pop();
+var script = _.util.currentScript();
 
-  if (script) {
-    _.filename = script.src;
+if (script) {
+  _.filename = script.src;
 
-    if (!_.manual && !script.hasAttribute('data-manual')) {
-      if(document.readyState !== "loading") {
-        if (window.requestAnimationFrame) {
-          window.requestAnimationFrame(_.highlightAll);
-        } else {
-          window.setTimeout(_.highlightAll, 16);
-        }
-      }
-      else {
-        document.addEventListener('DOMContentLoaded', _.highlightAll);
-      }
+  if (script.hasAttribute('data-manual')) {
+    _.manual = true;
+  }
+}
+
+if (!_.manual) {
+  function highlightAutomaticallyCallback() {
+    if (!_.manual) {
+      _.highlightAll();
     }
   }
 
-  return _;
+  // If the document state is "loading", then we'll use DOMContentLoaded.
+  // If the document state is "interactive" and the prism.js script is deferred, then we'll also use the
+  // DOMContentLoaded event because there might be some plugins or languages which have also been deferred 
and they
+  // might take longer one animation frame to execute which can create a race condition where only some 
plugins have
+  // been loaded when Prism.highlightAll() is executed, depending on how fast resources are loaded.
+  // See https://github.com/PrismJS/prism/issues/2102
+  var readyState = document.readyState;
+  if (readyState === 'loading' || readyState === 'interactive' && script && script.defer) {
+    document.addEventListener('DOMContentLoaded', highlightAutomaticallyCallback);
+  } else {
+    if (window.requestAnimationFrame) {
+      window.requestAnimationFrame(highlightAutomaticallyCallback);
+    } else {
+      window.setTimeout(highlightAutomaticallyCallback, 16);
+    }
+  }
+}
+
+return _;
 
 })(_self);
 
@@ -555,7 +625,10 @@ if (typeof global !== 'undefined') {
 Prism.languages.markup = {
   'comment': /<!--[\s\S]*?-->/,
   'prolog': /<\?[\s\S]+?\?>/,
-  'doctype': /<!DOCTYPE[\s\S]+?>/i,
+  'doctype': {
+    pattern: 
/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:(?!<!--)[^"'\]]|"[^"]*"|'[^']*'|<!--[\s\S]*?-->)*\]\s*)?>/i,
+    greedy: true
+  },
   'cdata': /<!\[CDATA\[[\s\S]*?]]>/i,
   'tag': {
     pattern: 
/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/i,
@@ -728,17 +801,17 @@ Prism.languages.clike = {
     greedy: true
   },
   'class-name': {
-    pattern: 
/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,
+    pattern: /(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,
     lookbehind: true,
     inside: {
-      punctuation: /[.\\]/
+      'punctuation': /[.\\]/
     }
   },
   'keyword': 
/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,
   'boolean': /\b(?:true|false)\b/,
   'function': /\w+(?=\()/,
   'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,
-  'operator': /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,
+  'operator': /[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,
   'punctuation': /[{}[\];(),.:]/
 };
 
@@ -756,21 +829,21 @@ Prism.languages.javascript = Prism.languages.extend('clike', {
       lookbehind: true
     },
     {
-      pattern: 
/(^|[^.])\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,
+      pattern: 
/(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,
       lookbehind: true
     },
   ],
   'number': 
/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,
   // Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
   'function': /#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,
-  'operator': 
/-[-=]?|\+[+=]?|!=?=?|<<?=?|>>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/
+  'operator': /--|\+\+|\*\*=?|=>|&&|\|\||[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?[.?]?|[~:]/
 });
 
 Prism.languages.javascript['class-name'][0].pattern = 
/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/;
 
 Prism.languages.insertBefore('javascript', 'keyword', {
   'regex': {
-    pattern: 
/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=\s*($|[\r\n,.;})\]]))/,
+    pattern: 
/((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*[\s\S]*?\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,
     lookbehind: true,
     greedy: true
   },
@@ -834,43 +907,6 @@ if (Prism.languages.markup) {
 
 Prism.languages.js = Prism.languages.javascript;
 
-Prism.languages.c = Prism.languages.extend('clike', {
-  'class-name': {
-    pattern: /(\b(?:enum|struct)\s+)\w+/,
-    lookbehind: true
-  },
-  'keyword': 
/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,
-  'operator': />>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/,
-  'number': 
/(?:\b0x(?:[\da-f]+\.?[\da-f]*|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i
-});
-
-Prism.languages.insertBefore('c', 'string', {
-  'macro': {
-    // allow for multiline macro definitions
-    // spaces after the # character compile fine with gcc
-    pattern: /(^\s*)#\s*[a-z]+(?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im,
-    lookbehind: true,
-    alias: 'property',
-    inside: {
-      // highlight the path of the include statement as a string
-      'string': {
-        pattern: /(#\s*include\s*)(?:<.+?>|("|')(?:\\?.)+?\2)/,
-        lookbehind: true
-      },
-      // highlight macro directives as keywords
-      'directive': {
-        pattern: 
/(#\s*)\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,
-        lookbehind: true,
-        alias: 'keyword'
-      }
-    }
-  },
-  // highlight predefined macros as constants
-  'constant': 
/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/
-});
-
-delete Prism.languages.c['boolean'];
-
 (function(Prism) {
   // $ set | grep '^[A-Z][^[:space:]]*=' | cut -d= -f1 | tr '\n' '|'
   // + LC_ALL, RANDOM, REPLY, SECONDS.
@@ -980,7 +1016,7 @@ delete Prism.languages.c['boolean'];
     'string': [
       // Support for Here-documents https://en.wikipedia.org/wiki/Here_document
       {
-        pattern: /((?:^|[^<])<<-?\s*)(\w+?)\s*(?:\r?\n|\r)(?:[\s\S])*?(?:\r?\n|\r)\2/,
+        pattern: /((?:^|[^<])<<-?\s*)(\w+?)\s*(?:\r?\n|\r)[\s\S]*?(?:\r?\n|\r)\2/,
         lookbehind: true,
         greedy: true,
         inside: insideString
@@ -988,7 +1024,7 @@ delete Prism.languages.c['boolean'];
       // Here-document with quotes around the tag
       // → No expansion (so no “inside”).
       {
-        pattern: /((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s*(?:\r?\n|\r)(?:[\s\S])*?(?:\r?\n|\r)\3/,
+        pattern: /((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s*(?:\r?\n|\r)[\s\S]*?(?:\r?\n|\r)\3/,
         lookbehind: true,
         greedy: true
       },
@@ -1069,125 +1105,162 @@ delete Prism.languages.c['boolean'];
   Prism.languages.shell = Prism.languages.bash;
 })(Prism);
 
-Prism.languages.cpp = Prism.languages.extend('c', {
+Prism.languages.c = Prism.languages.extend('clike', {
   'class-name': {
-    pattern: /(\b(?:class|enum|struct)\s+)\w+/,
+    pattern: /(\b(?:enum|struct)\s+)\w+/,
     lookbehind: true
   },
-  'keyword': 
/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,
-  'number': {
-    pattern: 
/(?:\b0b[01']+|\b0x(?:[\da-f']+\.?[\da-f']*|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+\.?[\d']*|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]*/i,
-    greedy: true
-  },
-  'operator': 
/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,
-  'boolean': /\b(?:true|false)\b/
-});
-
-Prism.languages.insertBefore('cpp', 'string', {
-  'raw-string': {
-    pattern: /R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,
-    alias: 'string',
-    greedy: true
-  }
+  'keyword': 
/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,
+  'operator': />>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/,
+  'number': 
/(?:\b0x(?:[\da-f]+\.?[\da-f]*|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i
 });
 
-(function(Prism) {
-
-// Ignore comments starting with { to privilege string interpolation highlighting
-  var comment = /#(?!\{).+/,
-    interpolation = {
-      pattern: /#\{[^}]+\}/,
-      alias: 'variable'
-    };
-
-  Prism.languages.coffeescript = Prism.languages.extend('javascript', {
-    'comment': comment,
-    'string': [
-
-      // Strings are multiline
-      {
-        pattern: /'(?:\\[\s\S]|[^\\'])*'/,
-        greedy: true
+Prism.languages.insertBefore('c', 'string', {
+  'macro': {
+    // allow for multiline macro definitions
+    // spaces after the # character compile fine with gcc
+    pattern: /(^\s*)#\s*[a-z]+(?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im,
+    lookbehind: true,
+    alias: 'property',
+    inside: {
+      // highlight the path of the include statement as a string
+      'string': {
+        pattern: /(#\s*include\s*)(?:<.+?>|("|')(?:\\?.)+?\2)/,
+        lookbehind: true
       },
-
-      {
-        // Strings are multiline
-        pattern: /"(?:\\[\s\S]|[^\\"])*"/,
-        greedy: true,
-        inside: {
-          'interpolation': interpolation
-        }
+      // highlight macro directives as keywords
+      'directive': {
+        pattern: 
/(#\s*)\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,
+        lookbehind: true,
+        alias: 'keyword'
       }
-    ],
-    'keyword': 
/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,
-    'class-member': {
-      pattern: /@(?!\d)\w+/,
-      alias: 'variable'
     }
-  });
+  },
+  // highlight predefined macros as constants
+  'constant': 
/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/
+});
 
-  Prism.languages.insertBefore('coffeescript', 'comment', {
-    'multiline-comment': {
-      pattern: /###[\s\S]+?###/,
-      alias: 'comment'
+delete Prism.languages.c['boolean'];
+
+Prism.languages.cpp = Prism.languages.extend('c', {
+  'class-name': {
+    pattern: /(\b(?:class|enum|struct)\s+)\w+/,
+    lookbehind: true
+  },
+  'keyword': 
/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,
+  'number': {
+    pattern: 
/(?:\b0b[01']+|\b0x(?:[\da-f']+\.?[\da-f']*|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+\.?[\d']*|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]*/i,
+    greedy: true
+  },
+  'operator': 
/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,
+  'boolean': /\b(?:true|false)\b/
+});
+
+Prism.languages.insertBefore('cpp', 'string', {
+  'raw-string': {
+    pattern: /R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,
+    alias: 'string',
+    greedy: true
+  }
+});
+
+(function(Prism) {
+
+// Ignore comments starting with { to privilege string interpolation highlighting
+var comment = /#(?!\{).+/,
+    interpolation = {
+      pattern: /#\{[^}]+\}/,
+      alias: 'variable'
+    };
+
+Prism.languages.coffeescript = Prism.languages.extend('javascript', {
+  'comment': comment,
+  'string': [
+
+    // Strings are multiline
+    {
+      pattern: /'(?:\\[\s\S]|[^\\'])*'/,
+      greedy: true
     },
 
-    // Block regexp can contain comments and interpolation
-    'block-regex': {
-      pattern: /\/{3}[\s\S]*?\/{3}/,
-      alias: 'regex',
+    {
+      // Strings are multiline
+      pattern: /"(?:\\[\s\S]|[^\\"])*"/,
+      greedy: true,
       inside: {
-        'comment': comment,
         'interpolation': interpolation
       }
     }
-  });
+  ],
+  'keyword': 
/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,
+  'class-member': {
+    pattern: /@(?!\d)\w+/,
+    alias: 'variable'
+  }
+});
 
-  Prism.languages.insertBefore('coffeescript', 'string', {
-    'inline-javascript': {
-      pattern: /`(?:\\[\s\S]|[^\\`])*`/,
-      inside: {
-        'delimiter': {
-          pattern: /^`|`$/,
-          alias: 'punctuation'
-        },
-        rest: Prism.languages.javascript
-      }
-    },
+Prism.languages.insertBefore('coffeescript', 'comment', {
+  'multiline-comment': {
+    pattern: /###[\s\S]+?###/,
+    alias: 'comment'
+  },
 
-    // Block strings
-    'multiline-string': [
-      {
-        pattern: /'''[\s\S]*?'''/,
-        greedy: true,
-        alias: 'string'
+  // Block regexp can contain comments and interpolation
+  'block-regex': {
+    pattern: /\/{3}[\s\S]*?\/{3}/,
+    alias: 'regex',
+    inside: {
+      'comment': comment,
+      'interpolation': interpolation
+    }
+  }
+});
+
+Prism.languages.insertBefore('coffeescript', 'string', {
+  'inline-javascript': {
+    pattern: /`(?:\\[\s\S]|[^\\`])*`/,
+    inside: {
+      'delimiter': {
+        pattern: /^`|`$/,
+        alias: 'punctuation'
       },
-      {
-        pattern: /"""[\s\S]*?"""/,
-        greedy: true,
-        alias: 'string',
-        inside: {
-          interpolation: interpolation
-        }
+      rest: Prism.languages.javascript
+    }
+  },
+
+  // Block strings
+  'multiline-string': [
+    {
+      pattern: /'''[\s\S]*?'''/,
+      greedy: true,
+      alias: 'string'
+    },
+    {
+      pattern: /"""[\s\S]*?"""/,
+      greedy: true,
+      alias: 'string',
+      inside: {
+        interpolation: interpolation
       }
-    ]
+    }
+  ]
 
-  });
+});
 
-  Prism.languages.insertBefore('coffeescript', 'keyword', {
-    // Object property
-    'property': /(?!\d)\w+(?=\s*:(?!:))/
-  });
+Prism.languages.insertBefore('coffeescript', 'keyword', {
+  // Object property
+  'property': /(?!\d)\w+(?=\s*:(?!:))/
+});
 
-  delete Prism.languages.coffeescript['template-string'];
+delete Prism.languages.coffeescript['template-string'];
 
-  Prism.languages.coffee = Prism.languages.coffeescript;
+Prism.languages.coffee = Prism.languages.coffeescript;
 }(Prism));
 /**
  * Original by Samuel Flores
  *
  * Adds the following new token classes:
- *             constant, builtin, variable, symbol, regex
+ *     constant, builtin, variable, symbol, regex
  */
 (function(Prism) {
   Prism.languages.ruby = Prism.languages.extend('clike', {
@@ -1198,7 +1271,14 @@ Prism.languages.insertBefore('cpp', 'string', {
         greedy: true
       }
     ],
-    'keyword': 
/\b(?:alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|false|for|if|in|module|new|next|nil|not|or|protected|private|public|raise|redo|require|rescue|retry|return|self|super|then|throw|true|undef|unless|until|when|while|yield)\b/
+    'class-name': {
+      pattern: /(\b(?:class)\s+|\bcatch\s+\()[\w.\\]+/i,
+      lookbehind: true,
+      inside: {
+        'punctuation': /[.\\]/
+      }
+    },
+    'keyword': 
/\b(?:alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|protected|private|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/
   });
 
   var interpolation = {
@@ -1253,7 +1333,7 @@ Prism.languages.insertBefore('cpp', 'string', {
         }
       },
       {
-        pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\\\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/,
+        pattern: /(^|[^/])\/(?!\/)(?:\[.+?]|\\.|[^/\\\r\n])+\/[gim]{0,3}(?=\s*(?:$|[\r\n,.;})]))/,
         lookbehind: true,
         greedy: true
       }
@@ -1327,22 +1407,109 @@ Prism.languages.insertBefore('cpp', 'string', {
   Prism.languages.rb = Prism.languages.ruby;
 }(Prism));
 
+(function(Prism) {
+  Prism.languages.crystal = Prism.languages.extend('ruby', {
+    keyword: [
+      
/\b(?:abstract|alias|as|asm|begin|break|case|class|def|do|else|elsif|end|ensure|enum|extend|for|fun|if|include|instance_sizeof|lib|macro|module|next|of|out|pointerof|private|protected|rescue|return|require|select|self|sizeof|struct|super|then|type|typeof|uninitialized|union|unless|until|when|while|with|yield|__DIR__|__END_LINE__|__FILE__|__LINE__)\b/,
+      {
+        pattern: /(\.\s*)(?:is_a|responds_to)\?/,
+        lookbehind: true
+      }
+    ],
+
+    number: 
/\b(?:0b[01_]*[01]|0o[0-7_]*[0-7]|0x[\da-fA-F_]*[\da-fA-F]|(?:\d(?:[\d_]*\d)?)(?:\.[\d_]*\d)?(?:[eE][+-]?[\d_]*\d)?)(?:_(?:[uif](?:8|16|32|64))?)?\b/
+  });
+
+  Prism.languages.insertBefore('crystal', 'string', {
+    attribute: {
+      pattern: /@\[.+?\]/,
+      alias: 'attr-name',
+      inside: {
+        delimiter: {
+          pattern: /^@\[|\]$/,
+          alias: 'tag'
+        },
+        rest: Prism.languages.crystal
+      }
+    },
+
+    expansion: [
+    {
+      pattern: /\{\{.+?\}\}/,
+      inside: {
+        delimiter: {
+          pattern: /^\{\{|\}\}$/,
+          alias: 'tag'
+        },
+        rest: Prism.languages.crystal
+      }
+    },
+    {
+      pattern: /\{%.+?%\}/,
+      inside: {
+        delimiter: {
+          pattern: /^\{%|%\}$/,
+          alias: 'tag'
+        },
+        rest: Prism.languages.crystal
+      }
+    }
+    ]
+  });
+
+}(Prism));
+
 Prism.languages.d = Prism.languages.extend('clike', {
+  'comment': [
+    {
+      // Shebang
+      pattern: /^\s*#!.+/,
+      greedy: true
+    },
+    {
+      pattern: RegExp(/(^|[^\\])/.source + '(?:' + [
+        // /+ comment +/
+        // Allow one level of nesting
+        /\/\+(?:\/\+[\s\S]*?\+\/|(?!\/\+)[\s\S])*?\+\//.source,
+        // // comment
+        /\/\/.*/.source,
+        // /* comment */
+        /\/\*[\s\S]*?\*\//.source
+      ].join('|') + ')'),
+      lookbehind: true,
+      greedy: true
+    }
+  ],
   'string': [
-    // r"", x""
-    /\b[rx]"(?:\\[\s\S]|[^\\"])*"[cwd]?/,
-    // q"[]", q"()", q"<>", q"{}"
-    /\bq"(?:\[[\s\S]*?\]|\([\s\S]*?\)|<[\s\S]*?>|\{[\s\S]*?\})"/,
-    // q"IDENT
-    // ...
-    // IDENT"
-    /\bq"([_a-zA-Z][_a-zA-Z\d]*)(?:\r?\n|\r)[\s\S]*?(?:\r?\n|\r)\1"/,
-    // q"//", q"||", etc.
-    /\bq"(.)[\s\S]*?\1"/,
-    // Characters
-    /'(?:\\'|\\?[^']+)'/,
-
-    /(["`])(?:\\[\s\S]|(?!\1)[^\\])*\1[cwd]?/
+    {
+      pattern: RegExp([
+        // r"", x""
+        /\b[rx]"(?:\\[\s\S]|[^\\"])*"[cwd]?/.source,
+
+        // q"[]", q"()", q"<>", q"{}"
+        /\bq"(?:\[[\s\S]*?\]|\([\s\S]*?\)|<[\s\S]*?>|\{[\s\S]*?\})"/.source,
+
+        // q"IDENT
+        // ...
+        // IDENT"
+        /\bq"((?!\d)\w+)$[\s\S]*?^\1"/.source,
+
+        // q"//", q"||", etc.
+        /\bq"(.)[\s\S]*?\2"/.source,
+
+        // Characters
+        // 'a', '\\', '\n', '\xFF', '\377', '\uFFFF', '\U0010FFFF', '\quot'
+        /'(?:\\(?:\W|\w+)|[^\\])'/.source,
+
+        /(["`])(?:\\[\s\S]|(?!\3)[^\\])*\3[cwd]?/.source
+      ].join('|'), 'm'),
+      greedy: true
+    },
+    {
+      pattern: /\bq\{(?:\{[^{}]*\}|[^{}])*\}/,
+      greedy: true,
+      alias: 'token-string'
+    }
   ],
 
   'number': [
@@ -1360,26 +1527,6 @@ Prism.languages.d = Prism.languages.extend('clike', {
   'operator': 
/\|[|=]?|&[&=]?|\+[+=]?|-[-=]?|\.?\.\.|=[>=]?|!(?:i[ns]\b|<>?=?|>=?|=)?|\bi[ns]\b|(?:<[<>]?|>>?>?|\^\^|[*\/%^~])=?/
 });
 
-
-Prism.languages.d.comment = [
-  // Shebang
-  /^\s*#!.+/,
-  // /+ +/
-  {
-    // Allow one level of nesting
-    pattern: /(^|[^\\])\/\+(?:\/\+[\s\S]*?\+\/|[\s\S])*?\+\//,
-    lookbehind: true
-  }
-].concat(Prism.languages.d.comment);
-
-Prism.languages.insertBefore('d', 'comment', {
-  'token-string': {
-    // Allow one level of nesting
-    pattern: /\bq\{(?:\{[^}]*\}|[^}])*\}/,
-    alias: 'string'
-  }
-});
-
 Prism.languages.insertBefore('d', 'keyword', {
   'property': /\B@\w*/
 });
@@ -1391,6 +1538,7 @@ Prism.languages.insertBefore('d', 'function', {
     alias: 'variable'
   }
 });
+
 Prism.languages.dart = Prism.languages.extend('clike', {
   'string': [
     {
@@ -1539,50 +1687,111 @@ Prism.languages.insertBefore('dart','function',{
 
 }(Prism));
 
-Prism.languages.elixir = {
-  'comment': /#.*/m,
-  // ~r"""foo""" (multi-line), ~r'''foo''' (multi-line), ~r/foo/, ~r|foo|, ~r"foo", ~r'foo', ~r(foo), 
~r[foo], ~r{foo}, ~r<foo>
-  'regex': {
-    pattern: 
/~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/,
-    greedy: true
-  },
-  'string': [
-    {
-      // ~s"""foo""" (multi-line), ~s'''foo''' (multi-line), ~s/foo/, ~s|foo|, ~s"foo", ~s'foo', ~s(foo), 
~s[foo], ~s{foo} (with interpolation care), ~s<foo>
-      pattern: 
/~[cCsSwW](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|#\{[^}]+\}|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[csa]?/,
-      greedy: true,
-      inside: {
-        // See interpolation below
-      }
+// Django/Jinja2 syntax definition for Prism.js <http://prismjs.com> syntax highlighter.
+// Mostly it works OK but can paint code incorrectly on complex html/template tag combinations.
+
+(function (Prism) {
+
+  Prism.languages.django = {
+    'comment': /^{#[\s\S]*?#}$/,
+    'tag': {
+      pattern: /(^{%[+-]?\s*)\w+/,
+      lookbehind: true,
+      alias: 'keyword'
     },
-    {
-      pattern: /("""|''')[\s\S]*?\1/,
-      greedy: true,
-      inside: {
-        // See interpolation below
-      }
+    'delimiter': {
+      pattern: /^{[{%][+-]?|[+-]?[}%]}$/,
+      alias: 'punctuation'
     },
-    {
-      // Multi-line strings are allowed
-      pattern: /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
-      greedy: true,
-      inside: {
-        // See interpolation below
-      }
-    }
-  ],
-  'atom': {
-    // Look-behind prevents bad highlighting of the :: operator
-    pattern: /(^|[^:]):\w+/,
-    lookbehind: true,
-    alias: 'symbol'
-  },
-  // Look-ahead prevents bad highlighting of the :: operator
-  'attr-name': /\w+:(?!:)/,
-  'capture': {
-    // Look-behind prevents bad highlighting of the && operator
-    pattern: /(^|[^&])&(?:[^&\s\d()][^\s()]*|(?=\())/,
-    lookbehind: true,
+    'string': {
+      pattern: /("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,
+      greedy: true
+    },
+    'filter': {
+      pattern: /(\|)\w+/,
+      lookbehind: true,
+      alias: 'function'
+    },
+    'test': {
+      pattern: /(\bis\s+(?:not\s+)?)(?!not\b)\w+/,
+      lookbehind: true,
+      alias: 'function'
+    },
+    'function': /\b[a-z_]\w+(?=\s*\()/i,
+    'keyword': /\b(?:and|as|by|else|for|if|import|in|is|loop|not|or|recursive|with|without)\b/,
+    'operator': /[-+*/%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,
+    'number': /\b\d+(?:\.\d+)?\b/,
+    'boolean': /[Tt]rue|[Ff]alse|[Nn]one/,
+    'variable': /\b\w+?\b/,
+    'punctuation': /[{}[\](),.:;]/
+  };
+
+
+  var pattern = /{{[\s\S]*?}}|{%[\s\S]*?%}|{#[\s\S]*?#}/g;
+  var markupTemplating = Prism.languages['markup-templating'];
+
+  Prism.hooks.add('before-tokenize', function (env) {
+    markupTemplating.buildPlaceholders(env, 'django', pattern);
+  });
+  Prism.hooks.add('after-tokenize', function (env) {
+    markupTemplating.tokenizePlaceholders(env, 'django');
+  });
+
+  // Add an Jinja2 alias
+  Prism.languages.jinja2 = Prism.languages.django;
+  Prism.hooks.add('before-tokenize', function (env) {
+    markupTemplating.buildPlaceholders(env, 'jinja2', pattern);
+  });
+  Prism.hooks.add('after-tokenize', function (env) {
+    markupTemplating.tokenizePlaceholders(env, 'jinja2');
+  });
+
+})(Prism);
+
+Prism.languages.elixir = {
+  'comment': /#.*/m,
+  // ~r"""foo""" (multi-line), ~r'''foo''' (multi-line), ~r/foo/, ~r|foo|, ~r"foo", ~r'foo', ~r(foo), 
~r[foo], ~r{foo}, ~r<foo>
+  'regex': {
+    pattern: 
/~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/,
+    greedy: true
+  },
+  'string': [
+    {
+      // ~s"""foo""" (multi-line), ~s'''foo''' (multi-line), ~s/foo/, ~s|foo|, ~s"foo", ~s'foo', ~s(foo), 
~s[foo], ~s{foo} (with interpolation care), ~s<foo>
+      pattern: 
/~[cCsSwW](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|#\{[^}]+\}|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[csa]?/,
+      greedy: true,
+      inside: {
+        // See interpolation below
+      }
+    },
+    {
+      pattern: /("""|''')[\s\S]*?\1/,
+      greedy: true,
+      inside: {
+        // See interpolation below
+      }
+    },
+    {
+      // Multi-line strings are allowed
+      pattern: /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
+      greedy: true,
+      inside: {
+        // See interpolation below
+      }
+    }
+  ],
+  'atom': {
+    // Look-behind prevents bad highlighting of the :: operator
+    pattern: /(^|[^:]):\w+/,
+    lookbehind: true,
+    alias: 'symbol'
+  },
+  // Look-ahead prevents bad highlighting of the :: operator
+  'attr-name': /\w+\??:(?!:)/,
+  'capture': {
+    // Look-behind prevents bad highlighting of the && operator
+    pattern: /(^|[^&])&(?:[^&\s\d()][^\s()]*|(?=\())/,
+    lookbehind: true,
     alias: 'function'
   },
   'argument': {
@@ -1680,30 +1889,32 @@ Prism.languages.go = Prism.languages.extend('clike', {
   'operator': /[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,
   'number': /(?:\b0x[a-f\d]+|(?:\b\d+\.?\d*|\B\.\d+)(?:e[-+]?\d+)?)i?/i,
   'string': {
-    pattern: /(["'`])(\\[\s\S]|(?!\1)[^\\])*\1/,
+    pattern: /(["'`])(?:\\[\s\S]|(?!\1)[^\\])*\1/,
     greedy: true
   }
 });
 delete Prism.languages.go['class-name'];
 
 Prism.languages.groovy = Prism.languages.extend('clike', {
-  'keyword': 
/\b(?:as|def|in|abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|trait|transient|try|void|volatile|while)\b/,
   'string': [
     {
-      pattern: /("""|''')[\s\S]*?\1|(?:\$\/)(?:\$\/\$|[\s\S])*?\/\$/,
+      pattern: /("""|''')(?:[^\\]|\\[\s\S])*?\1|\$\/(?:\$\/\$|[\s\S])*?\/\$/,
       greedy: true
     },
     {
-      pattern: /(["'\/])(?:\\.|(?!\1)[^\\\r\n])*\1/,
+      // TODO: Slash strings (e.g. /foo/) can contain line breaks but this will cause a lot of trouble with
+      // simple division (see JS regex), so find a fix maybe?
+      pattern: /(["'/])(?:\\.|(?!\1)[^\\\r\n])*\1/,
       greedy: true
     }
   ],
+  'keyword': 
/\b(?:as|def|in|abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|trait|transient|try|void|volatile|while)\b/,
   'number': /\b(?:0b[01_]+|0x[\da-f_]+(?:\.[\da-f_p\-]+)?|[\d_]+(?:\.[\d_]+)?(?:e[+-]?[\d]+)?)[glidf]?\b/i,
   'operator': {
-    pattern: 
/(^|[^.])(?:~|==?~?|\?[.:]?|\*(?:[.=]|\*=?)?|\.[@&]|\.\.<|\.{1,2}(?!\.)|-[-=>]?|\+[+=]?|!=?|<(?:<=?|=>?)?|>(?:>>?=?|=)?|&[&=]?|\|[|=]?|\/=?|\^=?|%=?)/,
+    pattern: 
/(^|[^.])(?:~|==?~?|\?[.:]?|\*(?:[.=]|\*=?)?|\.[@&]|\.\.<|\.\.(?!\.)|-[-=>]?|\+[+=]?|!=?|<(?:<=?|=>?)?|>(?:>>?=?|=)?|&[&=]?|\|[|=]?|\/=?|\^=?|%=?)/,
     lookbehind: true
   },
-  'punctuation': /\.+|[{}[\];(),:$]/
+  'punctuation': /\.+|[{}[\];(),.:$]/
 });
 
 Prism.languages.insertBefore('groovy', 'string', {
@@ -1719,9 +1930,9 @@ Prism.languages.insertBefore('groovy', 'punctuation', {
 
 Prism.languages.insertBefore('groovy', 'function', {
   'annotation': {
-    alias: 'punctuation',
     pattern: /(^|[^.])@\w+/,
-    lookbehind: true
+    lookbehind: true,
+    alias: 'punctuation'
   }
 });
 
@@ -1754,7 +1965,7 @@ Prism.hooks.add('wrap', function(env) {
 
 (function (Prism) {
 
-  var keywords = 
/\b(?:abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while|var|null|exports|module|open|opens|provides|requires|to|transitive|uses|with)\b/;
+  var keywords = 
/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|null|open|opens|package|private|protected|provides|public|requires|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/;
 
   // based on the java naming conventions
   var className = /\b[A-Z](?:\w*[a-z]\w*)?\b/;
@@ -1777,11 +1988,20 @@ Prism.hooks.add('wrap', function(env) {
     ],
     'number': 
/\b0b[01][01_]*L?\b|\b0x[\da-f_]*\.?[\da-f_p+-]+\b|(?:\b\d[\d_]*\.?[\d_]*|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,
     'operator': {
-      pattern: /(^|[^.])(?:<<=?|>>>?=?|->|([-+&|])\2|[?:~]|[-+*/%&|^!=<>]=?)/m,
+      pattern: /(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,
       lookbehind: true
     }
   });
 
+  Prism.languages.insertBefore('java', 'string', {
+    'triple-quoted-string': {
+      // http://openjdk.java.net/jeps/355#Description
+      pattern: /"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,
+      greedy: true,
+      alias: 'string'
+    }
+  });
+
   Prism.languages.insertBefore('java', 'class-name', {
     'annotation': {
       alias: 'punctuation',
@@ -1789,7 +2009,7 @@ Prism.hooks.add('wrap', function(env) {
       lookbehind: true
     },
     'namespace': {
-      pattern: 
/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)[a-z]\w*(\.[a-z]\w*)+/,
+      pattern: 
/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)[a-z]\w*(?:\.[a-z]\w*)+/,
       lookbehind: true,
       inside: {
         'punctuation': /\./,
@@ -1807,139 +2027,6 @@ Prism.hooks.add('wrap', function(env) {
   });
 }(Prism));
 
-/**
- * Original by Aaron Harun: http://aahacreative.com/2012/07/31/php-syntax-highlighting-prism/
- * Modified by Miles Johnson: http://milesj.me
- *
- * Supports the following:
- *             - Extends clike syntax
- *             - Support for PHP 5.3+ (namespaces, traits, generators, etc)
- *             - Smarter constant and function matching
- *
- * Adds the following new token classes:
- *             constant, delimiter, variable, function, package
- */
-(function (Prism) {
-  Prism.languages.php = Prism.languages.extend('clike', {
-    'keyword': 
/\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|new|or|parent|print|private|protected|public|require|require_once|return|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i,
-    'boolean': {
-      pattern: /\b(?:false|true)\b/i,
-      alias: 'constant'
-    },
-    'constant': [
-      /\b[A-Z_][A-Z0-9_]*\b/,
-      /\b(?:null)\b/i,
-    ],
-    'comment': {
-      pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,
-      lookbehind: true
-    }
-  });
-
-  Prism.languages.insertBefore('php', 'string', {
-    'shell-comment': {
-      pattern: /(^|[^\\])#.*/,
-      lookbehind: true,
-      alias: 'comment'
-    }
-  });
-
-  Prism.languages.insertBefore('php', 'comment', {
-    'delimiter': {
-      pattern: /\?>$|^<\?(?:php(?=\s)|=)?/i,
-      alias: 'important'
-    }
-  });
-
-  Prism.languages.insertBefore('php', 'keyword', {
-    'variable': /\$+(?:\w+\b|(?={))/i,
-    'package': {
-      pattern: /(\\|namespace\s+|use\s+)[\w\\]+/,
-      lookbehind: true,
-      inside: {
-        punctuation: /\\/
-      }
-    }
-  });
-
-  // Must be defined after the function pattern
-  Prism.languages.insertBefore('php', 'operator', {
-    'property': {
-      pattern: /(->)[\w]+/,
-      lookbehind: true
-    }
-  });
-
-  var string_interpolation = {
-    pattern: /{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[.+?]|->\w+)*)/,
-    lookbehind: true,
-    inside: {
-      rest: Prism.languages.php
-    }
-  };
-
-  Prism.languages.insertBefore('php', 'string', {
-    'nowdoc-string': {
-      pattern: /<<<'([^']+)'(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;/,
-      greedy: true,
-      alias: 'string',
-      inside: {
-        'delimiter': {
-          pattern: /^<<<'[^']+'|[a-z_]\w*;$/i,
-          alias: 'symbol',
-          inside: {
-            'punctuation': /^<<<'?|[';]$/
-          }
-        }
-      }
-    },
-    'heredoc-string': {
-      pattern: 
/<<<(?:"([^"]+)"(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;|([a-z_]\w*)(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\2;)/i,
-      greedy: true,
-      alias: 'string',
-      inside: {
-        'delimiter': {
-          pattern: /^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,
-          alias: 'symbol',
-          inside: {
-            'punctuation': /^<<<"?|[";]$/
-          }
-        },
-        'interpolation': string_interpolation // See below
-      }
-    },
-    'single-quoted-string': {
-      pattern: /'(?:\\[\s\S]|[^\\'])*'/,
-      greedy: true,
-      alias: 'string'
-    },
-    'double-quoted-string': {
-      pattern: /"(?:\\[\s\S]|[^\\"])*"/,
-      greedy: true,
-      alias: 'string',
-      inside: {
-        'interpolation': string_interpolation // See below
-      }
-    }
-  });
-  // The different types of PHP strings "replace" the C-like standard string
-  delete Prism.languages.php['string'];
-
-  Prism.hooks.add('before-tokenize', function(env) {
-    if (!/<\?/.test(env.code)) {
-      return;
-    }
-
-    var phpPattern = 
/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#)(?:[^?\n\r]|\?(?!>))*|\/\*[\s\S]*?(?:\*\/|$))*?(?:\?>|$)/ig;
-    Prism.languages['markup-templating'].buildPlaceholders(env, 'php', phpPattern);
-  });
-
-  Prism.hooks.add('after-tokenize', function(env) {
-    Prism.languages['markup-templating'].tokenizePlaceholders(env, 'php');
-  });
-
-}(Prism));
-
 Prism.languages.json = {
   'property': {
     pattern: /"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,
@@ -1950,7 +2037,7 @@ Prism.languages.json = {
     greedy: true
   },
   'comment': /\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,
-  'number': /-?\d+\.?\d*(e[+-]?\d+)?/i,
+  'number': /-?\d+\.?\d*(?:e[+-]?\d+)?/i,
   'punctuation': /[{}[\],]/,
   'operator': /:/,
   'boolean': /\b(?:true|false)\b/,
@@ -2018,7 +2105,7 @@ Prism.languages.julia= {
     {
       pattern: /\$\{[^}]+\}/,
       inside: {
-        delimiter: {
+        'delimiter': {
           pattern: /^\$\{|\}$/,
           alias: 'variable'
         },
@@ -2037,58 +2124,6 @@ Prism.languages.julia= {
 
 }(Prism));
 
-(function(Prism) {
-  Prism.languages.crystal = Prism.languages.extend('ruby', {
-    keyword: [
-      
/\b(?:abstract|alias|as|asm|begin|break|case|class|def|do|else|elsif|end|ensure|enum|extend|for|fun|if|include|instance_sizeof|lib|macro|module|next|of|out|pointerof|private|protected|rescue|return|require|select|self|sizeof|struct|super|then|type|typeof|uninitialized|union|unless|until|when|while|with|yield|__DIR__|__END_LINE__|__FILE__|__LINE__)\b/,
-      {
-        pattern: /(\.\s*)(?:is_a|responds_to)\?/,
-        lookbehind: true
-      }
-    ],
-
-    number: 
/\b(?:0b[01_]*[01]|0o[0-7_]*[0-7]|0x[\da-fA-F_]*[\da-fA-F]|(?:\d(?:[\d_]*\d)?)(?:\.[\d_]*\d)?(?:[eE][+-]?[\d_]*\d)?)(?:_(?:[uif](?:8|16|32|64))?)?\b/
-  });
-
-  Prism.languages.insertBefore('crystal', 'string', {
-    attribute: {
-      pattern: /@\[.+?\]/,
-      alias: 'attr-name',
-      inside: {
-        delimiter: {
-          pattern: /^@\[|\]$/,
-          alias: 'tag'
-        },
-        rest: Prism.languages.crystal
-      }
-    },
-
-    expansion: [
-      {
-        pattern: /\{\{.+?\}\}/,
-        inside: {
-          delimiter: {
-            pattern: /^\{\{|\}\}$/,
-            alias: 'tag'
-          },
-          rest: Prism.languages.crystal
-        }
-      },
-      {
-        pattern: /\{%.+?%\}/,
-        inside: {
-          delimiter: {
-            pattern: /^\{%|%\}$/,
-            alias: 'tag'
-          },
-          rest: Prism.languages.crystal
-        }
-      }
-    ]
-  });
-
-}(Prism));
-
 Prism.languages.lua = {
   'comment': /^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)/m,
   // \z may be used to skip the following space
@@ -2109,67 +2144,6 @@ Prism.languages.lua = {
   ],
   'punctuation': /[\[\](){},;]|\.+|:+/
 };
-// Django/Jinja2 syntax definition for Prism.js <http://prismjs.com> syntax highlighter.
-// Mostly it works OK but can paint code incorrectly on complex html/template tag combinations.
-
-(function (Prism) {
-
-  Prism.languages.django = {
-    'comment': /^{#[\s\S]*?#}$/,
-    'tag': {
-      pattern: /(^{%[+-]?\s*)\w+/,
-      lookbehind: true,
-      alias: 'keyword'
-    },
-    'delimiter': {
-      pattern: /^{[{%][+-]?|[+-]?[}%]}$/,
-      alias: 'punctuation'
-    },
-    'string': {
-      pattern: /("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,
-      greedy: true
-    },
-    'filter': {
-      pattern: /(\|)\w+/,
-      lookbehind: true,
-      alias: 'function'
-    },
-    'test': {
-      pattern: /(\bis\s+(?:not\s+)?)(?!not\b)\w+/,
-      lookbehind: true,
-      alias: 'function'
-    },
-    'function': /\b[a-z_]\w+(?=\s*\()/i,
-    'keyword': /\b(?:and|as|by|else|for|if|import|in|is|loop|not|or|recursive|with|without)\b/,
-    'operator': /[-+*/%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,
-    'number': /\b\d+(?:\.\d+)?\b/,
-    'boolean': /[Tt]rue|[Ff]alse|[Nn]one/,
-    'variable': /\b\w+?\b/,
-    'punctuation': /[{}[\](),.:;]/
-  };
-
-
-  var pattern = /{{[\s\S]*?}}|{%[\s\S]*?%}|{#[\s\S]*?#}/g;
-  var markupTemplating = Prism.languages['markup-templating'];
-
-  Prism.hooks.add('before-tokenize', function (env) {
-    markupTemplating.buildPlaceholders(env, 'django', pattern);
-  });
-  Prism.hooks.add('after-tokenize', function (env) {
-    markupTemplating.tokenizePlaceholders(env, 'django');
-  });
-
-  // Add an Jinja2 alias
-  Prism.languages.jinja2 = Prism.languages.django;
-  Prism.hooks.add('before-tokenize', function (env) {
-    markupTemplating.buildPlaceholders(env, 'jinja2', pattern);
-  });
-  Prism.hooks.add('after-tokenize', function (env) {
-    markupTemplating.tokenizePlaceholders(env, 'jinja2');
-  });
-
-})(Prism);
-
 Prism.languages.matlab = {
   'comment': [
     /%\{[\s\S]*?\}%/,
@@ -2186,14 +2160,6 @@ Prism.languages.matlab = {
   'operator': /\.?[*^\/\\']|[+\-:@]|[<>=~]=?|&&?|\|\|?/,
   'punctuation': /\.{3}|[.,;\[\](){}!]/
 };
-Prism.languages.typescript = Prism.languages.extend('javascript', {
-  // From JavaScript Prism keyword list and TypeScript language spec: 
https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#221-reserved-words
-  'keyword': 
/\b(?:abstract|as|async|await|break|case|catch|class|const|constructor|continue|debugger|declare|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|is|keyof|let|module|namespace|new|null|of|package|private|protected|public|readonly|return|require|set|static|super|switch|this|throw|try|type|typeof|var|void|while|with|yield)\b/,
-  'builtin': /\b(?:string|Function|any|number|boolean|Array|symbol|console|Promise|unknown|never)\b/,
-});
-
-Prism.languages.ts = Prism.languages.typescript;
-
 Prism.languages.nginx = Prism.languages.extend('clike', {
   'comment': {
     pattern: /(^|[^"{\\])#.*/,
@@ -2388,7 +2354,7 @@ Prism.languages.perl = {
     // the same line from being highlighted as regex.
     // This does not support multi-line regex.
     {
-      pattern: 
/\/(?:[^\/\\\r\n]|\\.)*\/[msixpodualngc]*(?=\s*(?:$|[\r\n,.;})&|\-+*~<>!?^]|(lt|gt|le|ge|eq|ne|cmp|not|and|or|xor|x)\b))/,
+      pattern: 
/\/(?:[^\/\\\r\n]|\\.)*\/[msixpodualngc]*(?=\s*(?:$|[\r\n,.;})&|\-+*~<>!?^]|(?:lt|gt|le|ge|eq|ne|cmp|not|and|or|xor|x)\b))/,
       greedy: true
     }
   ],
@@ -2431,108 +2397,136 @@ Prism.languages.perl = {
   'punctuation': /[{}[\];(),:]/
 };
 
-Prism.languages.sql = {
-  'comment': {
-    pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,
-    lookbehind: true
-  },
-  'variable': [
-    {
-      pattern: /@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,
-      greedy: true
+/**
+ * Original by Aaron Harun: http://aahacreative.com/2012/07/31/php-syntax-highlighting-prism/
+ * Modified by Miles Johnson: http://milesj.me
+ *
+ * Supports the following:
+ *     - Extends clike syntax
+ *     - Support for PHP 5.3+ (namespaces, traits, generators, etc)
+ *     - Smarter constant and function matching
+ *
+ * Adds the following new token classes:
+ *     constant, delimiter, variable, function, package
+ */
+(function (Prism) {
+  Prism.languages.php = Prism.languages.extend('clike', {
+    'keyword': 
/\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|new|or|parent|print|private|protected|public|require|require_once|return|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i,
+    'boolean': {
+      pattern: /\b(?:false|true)\b/i,
+      alias: 'constant'
     },
-    /@[\w.$]+/
-  ],
-  'string': {
-    pattern: /(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,
-    greedy: true,
-    lookbehind: true
-  },
-  'function': /\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i, 
// Should we highlight user defined functions too?
-  'keyword': 
/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?:
 EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT
 
|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:_INSERT|COL)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURNS?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USE
 
R)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?:
 ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,
-  'boolean': /\b(?:TRUE|FALSE|NULL)\b/i,
-  'number': /\b0x[\da-f]+\b|\b\d+\.?\d*|\B\.\d+\b/i,
-  'operator': 
/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|IN|LIKE|NOT|OR|IS|DIV|REGEXP|RLIKE|SOUNDS 
LIKE|XOR)\b/i,
-  'punctuation': /[;[\]()`,.]/
-};
+    'constant': [
+      /\b[A-Z_][A-Z0-9_]*\b/,
+      /\b(?:null)\b/i,
+    ],
+    'comment': {
+      pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,
+      lookbehind: true
+    }
+  });
 
-Prism.languages.scss = Prism.languages.extend('css', {
-  'comment': {
-    pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,
-    lookbehind: true
-  },
-  'atrule': {
-    pattern: /@[\w-]+(?:\([^()]+\)|[^(])*?(?=\s+[{;])/,
-    inside: {
-      'rule': /@[\w-]+/
-      // See rest below
+  Prism.languages.insertBefore('php', 'string', {
+    'shell-comment': {
+      pattern: /(^|[^\\])#.*/,
+      lookbehind: true,
+      alias: 'comment'
     }
-  },
-  // url, compassified
-  'url': /(?:[-a-z]+-)?url(?=\()/i,
-  // CSS selector regex is not appropriate for Sass
-  // since there can be lot more things (var, @ directive, nesting..)
-  // a selector must start at the end of a property or after a brace (end of other rules or nesting)
-  // it can contain some characters that aren't used for defining rules or end of selector, & (parent 
selector), or interpolated variable
-  // the end of a selector is found when there is no rules in it ( {} or {\s}) or if there is a property 
(because an interpolated var
-  // can "pass" as a selector- e.g: proper#{$erty})
-  // this one was hard to do, so please be careful if you edit this one :)
-  'selector': {
-    // Initial look-ahead is used to prevent matching of blank selectors
-    pattern: /(?=\S)[^@;{}()]?(?:[^@;{}()]|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}]+[:{][^}]+))/m,
-    inside: {
-      'parent': {
-        pattern: /&/,
-        alias: 'important'
-      },
-      'placeholder': /%[-\w]+/,
-      'variable': /\$[-\w]+|#\{\$[-\w]+\}/
+  });
+
+  Prism.languages.insertBefore('php', 'comment', {
+    'delimiter': {
+      pattern: /\?>$|^<\?(?:php(?=\s)|=)?/i,
+      alias: 'important'
     }
-  },
-  'property': {
-    pattern: /(?:[\w-]|\$[-\w]+|#\{\$[-\w]+\})+(?=\s*:)/,
-    inside: {
-      'variable': /\$[-\w]+|#\{\$[-\w]+\}/
+  });
+
+  Prism.languages.insertBefore('php', 'keyword', {
+    'variable': /\$+(?:\w+\b|(?={))/i,
+    'package': {
+      pattern: /(\\|namespace\s+|use\s+)[\w\\]+/,
+      lookbehind: true,
+      inside: {
+        punctuation: /\\/
+      }
     }
-  }
-});
+  });
 
-Prism.languages.insertBefore('scss', 'atrule', {
-  'keyword': [
-    /@(?:if|else(?: if)?|for|each|while|import|extend|debug|warn|mixin|include|function|return|content)/i,
-    {
-      pattern: /( +)(?:from|through)(?= )/,
+  // Must be defined after the function pattern
+  Prism.languages.insertBefore('php', 'operator', {
+    'property': {
+      pattern: /(->)[\w]+/,
       lookbehind: true
     }
-  ]
-});
+  });
 
-Prism.languages.insertBefore('scss', 'important', {
-  // var and interpolated vars
-  'variable': /\$[-\w]+|#\{\$[-\w]+\}/
-});
+  var string_interpolation = {
+    pattern: /{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[.+?]|->\w+)*)/,
+    lookbehind: true,
+    inside: Prism.languages.php
+  };
 
-Prism.languages.insertBefore('scss', 'function', {
-  'placeholder': {
-    pattern: /%[-\w]+/,
-    alias: 'selector'
-  },
-  'statement': {
-    pattern: /\B!(?:default|optional)\b/i,
-    alias: 'keyword'
-  },
-  'boolean': /\b(?:true|false)\b/,
-  'null': {
-    pattern: /\bnull\b/,
-    alias: 'keyword'
-  },
-  'operator': {
-    pattern: /(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|or|not)(?=\s)/,
-    lookbehind: true
-  }
-});
+  Prism.languages.insertBefore('php', 'string', {
+    'nowdoc-string': {
+      pattern: /<<<'([^']+)'(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;/,
+      greedy: true,
+      alias: 'string',
+      inside: {
+        'delimiter': {
+          pattern: /^<<<'[^']+'|[a-z_]\w*;$/i,
+          alias: 'symbol',
+          inside: {
+            'punctuation': /^<<<'?|[';]$/
+          }
+        }
+      }
+    },
+    'heredoc-string': {
+      pattern: 
/<<<(?:"([^"]+)"(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;|([a-z_]\w*)(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\2;)/i,
+      greedy: true,
+      alias: 'string',
+      inside: {
+        'delimiter': {
+          pattern: /^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,
+          alias: 'symbol',
+          inside: {
+            'punctuation': /^<<<"?|[";]$/
+          }
+        },
+        'interpolation': string_interpolation // See below
+      }
+    },
+    'single-quoted-string': {
+      pattern: /'(?:\\[\s\S]|[^\\'])*'/,
+      greedy: true,
+      alias: 'string'
+    },
+    'double-quoted-string': {
+      pattern: /"(?:\\[\s\S]|[^\\"])*"/,
+      greedy: true,
+      alias: 'string',
+      inside: {
+        'interpolation': string_interpolation // See below
+      }
+    }
+  });
+  // The different types of PHP strings "replace" the C-like standard string
+  delete Prism.languages.php['string'];
 
-Prism.languages.scss['atrule'].inside.rest = Prism.languages.scss;
+  Prism.hooks.add('before-tokenize', function(env) {
+    if (!/<\?/.test(env.code)) {
+      return;
+    }
+
+    var phpPattern = 
/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#)(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|\/\*[\s\S]*?(?:\*\/|$))*?(?:\?>|$)/ig;
+    Prism.languages['markup-templating'].buildPlaceholders(env, 'php', phpPattern);
+  });
+
+  Prism.hooks.add('after-tokenize', function(env) {
+    Prism.languages['markup-templating'].tokenizePlaceholders(env, 'php');
+  });
+
+}(Prism));
 
 Prism.languages.python = {
   'comment': {
@@ -2580,7 +2574,7 @@ Prism.languages.python = {
     lookbehind: true
   },
   'decorator': {
-    pattern: /(^\s*)@\w+(?:\.\w+)*/i,
+    pattern: /(^\s*)@\w+(?:\.\w+)*/im,
     lookbehind: true,
     alias: ['annotation', 'punctuation'],
     inside: {
@@ -2598,138 +2592,139 @@ Prism.languages.python = {
 Prism.languages.python['string-interpolation'].inside['interpolation'].inside.rest = Prism.languages.python;
 
 Prism.languages.py = Prism.languages.python;
+
 (function(Prism) {
 
-  var javascript = Prism.util.clone(Prism.languages.javascript);
+var javascript = Prism.util.clone(Prism.languages.javascript);
 
-  Prism.languages.jsx = Prism.languages.extend('markup', javascript);
-  Prism.languages.jsx.tag.pattern= 
/<\/?(?:[\w.:-]+\s*(?:\s+(?:[\w.:-]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s{'">=]+|\{(?:\{(?:\{[^}]*\}|[^{}])*\}|[^{}])+\}))?|\{\.{3}[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\}))*\s*\/?)?>/i;
+Prism.languages.jsx = Prism.languages.extend('markup', javascript);
+Prism.languages.jsx.tag.pattern= 
/<\/?(?:[\w.:-]+\s*(?:\s+(?:[\w.:$-]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s{'">=]+|\{(?:\{(?:\{[^}]*\}|[^{}])*\}|[^{}])+\}))?|\{\s*\.{3}\s*[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\s*\}))*\s*\/?)?>/i;
 
-  Prism.languages.jsx.tag.inside['tag'].pattern = /^<\/?[^\s>\/]*/i;
-  Prism.languages.jsx.tag.inside['attr-value'].pattern = 
/=(?!\{)(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">]+)/i;
-  Prism.languages.jsx.tag.inside['tag'].inside['class-name'] = /^[A-Z]\w*(?:\.[A-Z]\w*)*$/;
+Prism.languages.jsx.tag.inside['tag'].pattern = /^<\/?[^\s>\/]*/i;
+Prism.languages.jsx.tag.inside['attr-value'].pattern = 
/=(?!\{)(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">]+)/i;
+Prism.languages.jsx.tag.inside['tag'].inside['class-name'] = /^[A-Z]\w*(?:\.[A-Z]\w*)*$/;
 
-  Prism.languages.insertBefore('inside', 'attr-name', {
-    'spread': {
-      pattern: /\{\.{3}[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\}/,
-      inside: {
-        'punctuation': /\.{3}|[{}.]/,
-        'attr-value': /\w+/
-      }
+Prism.languages.insertBefore('inside', 'attr-name', {
+  'spread': {
+    pattern: /\{\s*\.{3}\s*[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\s*\}/,
+    inside: {
+      'punctuation': /\.{3}|[{}.]/,
+      'attr-value': /\w+/
     }
-  }, Prism.languages.jsx.tag);
+  }
+}, Prism.languages.jsx.tag);
 
-  Prism.languages.insertBefore('inside', 'attr-value',{
-    'script': {
-      // Allow for two levels of nesting
-      pattern: /=(\{(?:\{(?:\{[^}]*\}|[^}])*\}|[^}])+\})/i,
-      inside: {
-        'script-punctuation': {
-          pattern: /^=(?={)/,
-          alias: 'punctuation'
-        },
-        rest: Prism.languages.jsx
+Prism.languages.insertBefore('inside', 'attr-value',{
+  'script': {
+    // Allow for two levels of nesting
+    pattern: /=(?:\{(?:\{(?:\{[^}]*\}|[^}])*\}|[^}])+\})/i,
+    inside: {
+      'script-punctuation': {
+        pattern: /^=(?={)/,
+        alias: 'punctuation'
       },
-      'alias': 'language-javascript'
-    }
-  }, Prism.languages.jsx.tag);
+      rest: Prism.languages.jsx
+    },
+    'alias': 'language-javascript'
+  }
+}, Prism.languages.jsx.tag);
 
 // The following will handle plain text inside tags
-  var stringifyToken = function (token) {
-    if (!token) {
-      return '';
-    }
-    if (typeof token === 'string') {
-      return token;
-    }
-    if (typeof token.content === 'string') {
-      return token.content;
-    }
-    return token.content.map(stringifyToken).join('');
-  };
+var stringifyToken = function (token) {
+  if (!token) {
+    return '';
+  }
+  if (typeof token === 'string') {
+    return token;
+  }
+  if (typeof token.content === 'string') {
+    return token.content;
+  }
+  return token.content.map(stringifyToken).join('');
+};
 
-  var walkTokens = function (tokens) {
-    var openedTags = [];
-    for (var i = 0; i < tokens.length; i++) {
-      var token = tokens[i];
-      var notTagNorBrace = false;
-
-      if (typeof token !== 'string') {
-        if (token.type === 'tag' && token.content[0] && token.content[0].type === 'tag') {
-          // We found a tag, now find its kind
-
-          if (token.content[0].content[0].content === '</') {
-            // Closing tag
-            if (openedTags.length > 0 && openedTags[openedTags.length - 1].tagName === 
stringifyToken(token.content[0].content[1])) {
-              // Pop matching opening tag
-              openedTags.pop();
-            }
+var walkTokens = function (tokens) {
+  var openedTags = [];
+  for (var i = 0; i < tokens.length; i++) {
+    var token = tokens[i];
+    var notTagNorBrace = false;
+
+    if (typeof token !== 'string') {
+      if (token.type === 'tag' && token.content[0] && token.content[0].type === 'tag') {
+        // We found a tag, now find its kind
+
+        if (token.content[0].content[0].content === '</') {
+          // Closing tag
+          if (openedTags.length > 0 && openedTags[openedTags.length - 1].tagName === 
stringifyToken(token.content[0].content[1])) {
+            // Pop matching opening tag
+            openedTags.pop();
+          }
+        } else {
+          if (token.content[token.content.length - 1].content === '/>') {
+            // Autoclosed tag, ignore
           } else {
-            if (token.content[token.content.length - 1].content === '/>') {
-              // Autoclosed tag, ignore
-            } else {
-              // Opening tag
-              openedTags.push({
-                tagName: stringifyToken(token.content[0].content[1]),
-                openedBraces: 0
-              });
-            }
+            // Opening tag
+            openedTags.push({
+              tagName: stringifyToken(token.content[0].content[1]),
+              openedBraces: 0
+            });
           }
-        } else if (openedTags.length > 0 && token.type === 'punctuation' && token.content === '{') {
+        }
+      } else if (openedTags.length > 0 && token.type === 'punctuation' && token.content === '{') {
 
-          // Here we might have entered a JSX context inside a tag
-          openedTags[openedTags.length - 1].openedBraces++;
+        // Here we might have entered a JSX context inside a tag
+        openedTags[openedTags.length - 1].openedBraces++;
 
-        } else if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces > 0 && token.type 
=== 'punctuation' && token.content === '}') {
+      } else if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces > 0 && token.type 
=== 'punctuation' && token.content === '}') {
 
-          // Here we might have left a JSX context inside a tag
-          openedTags[openedTags.length - 1].openedBraces--;
+        // Here we might have left a JSX context inside a tag
+        openedTags[openedTags.length - 1].openedBraces--;
 
-        } else {
-          notTagNorBrace = true
-        }
+      } else {
+        notTagNorBrace = true
       }
-      if (notTagNorBrace || typeof token === 'string') {
-        if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces === 0) {
-          // Here we are inside a tag, and not inside a JSX context.
-          // That's plain text: drop any tokens matched.
-          var plainText = stringifyToken(token);
-
-          // And merge text with adjacent text
-          if (i < tokens.length - 1 && (typeof tokens[i + 1] === 'string' || tokens[i + 1].type === 
'plain-text')) {
-            plainText += stringifyToken(tokens[i + 1]);
-            tokens.splice(i + 1, 1);
-          }
-          if (i > 0 && (typeof tokens[i - 1] === 'string' || tokens[i - 1].type === 'plain-text')) {
-            plainText = stringifyToken(tokens[i - 1]) + plainText;
-            tokens.splice(i - 1, 1);
-            i--;
-          }
+    }
+    if (notTagNorBrace || typeof token === 'string') {
+      if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces === 0) {
+        // Here we are inside a tag, and not inside a JSX context.
+        // That's plain text: drop any tokens matched.
+        var plainText = stringifyToken(token);
 
-          tokens[i] = new Prism.Token('plain-text', plainText, null, plainText);
+        // And merge text with adjacent text
+        if (i < tokens.length - 1 && (typeof tokens[i + 1] === 'string' || tokens[i + 1].type === 
'plain-text')) {
+          plainText += stringifyToken(tokens[i + 1]);
+          tokens.splice(i + 1, 1);
+        }
+        if (i > 0 && (typeof tokens[i - 1] === 'string' || tokens[i - 1].type === 'plain-text')) {
+          plainText = stringifyToken(tokens[i - 1]) + plainText;
+          tokens.splice(i - 1, 1);
+          i--;
         }
-      }
 
-      if (token.content && typeof token.content !== 'string') {
-        walkTokens(token.content);
+        tokens[i] = new Prism.Token('plain-text', plainText, null, plainText);
       }
     }
-  };
 
-  Prism.hooks.add('after-tokenize', function (env) {
-    if (env.language !== 'jsx' && env.language !== 'tsx') {
-      return;
+    if (token.content && typeof token.content !== 'string') {
+      walkTokens(token.content);
     }
-    walkTokens(env.tokens);
-  });
+  }
+};
+
+Prism.hooks.add('after-tokenize', function (env) {
+  if (env.language !== 'jsx' && env.language !== 'tsx') {
+    return;
+  }
+  walkTokens(env.tokens);
+});
 
 }(Prism));
 
 /* TODO
-       Add support for Markdown notation inside doc comments
-       Add support for nested block comments...
-       Match closure params even when not followed by dash or brace
-       Add better support for macro definition
+  Add support for Markdown notation inside doc comments
+  Add support for nested block comments...
+  Match closure params even when not followed by dash or brace
+  Add better support for macro definition
 */
 
 Prism.languages.rust = {
@@ -2780,7 +2775,7 @@ Prism.languages.rust = {
   },
 
   // Hex, oct, bin, dec numbers with visual separators and type suffix
-  'number': 
/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(\d(?:_?\d)*)?\.?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:[iu](?:8|16|32|64)?|f32|f64))?\b/,
+  'number': 
/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:\d(?:_?\d)*)?\.?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:[iu](?:8|16|32|64)?|f32|f64))?\b/,
 
   // Closure params should not be confused with bitwise OR |
   'closure-params': {
@@ -2794,6 +2789,160 @@ Prism.languages.rust = {
   'operator': /[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<<?=?|>>?=?|[@?]/
 };
 
+Prism.languages.scss = Prism.languages.extend('css', {
+  'comment': {
+    pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,
+    lookbehind: true
+  },
+  'atrule': {
+    pattern: /@[\w-]+(?:\([^()]+\)|[^(])*?(?=\s+[{;])/,
+    inside: {
+      'rule': /@[\w-]+/
+      // See rest below
+    }
+  },
+  // url, compassified
+  'url': /(?:[-a-z]+-)?url(?=\()/i,
+  // CSS selector regex is not appropriate for Sass
+  // since there can be lot more things (var, @ directive, nesting..)
+  // a selector must start at the end of a property or after a brace (end of other rules or nesting)
+  // it can contain some characters that aren't used for defining rules or end of selector, & (parent 
selector), or interpolated variable
+  // the end of a selector is found when there is no rules in it ( {} or {\s}) or if there is a property 
(because an interpolated var
+  // can "pass" as a selector- e.g: proper#{$erty})
+  // this one was hard to do, so please be careful if you edit this one :)
+  'selector': {
+    // Initial look-ahead is used to prevent matching of blank selectors
+    pattern: /(?=\S)[^@;{}()]?(?:[^@;{}()]|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}]+[:{][^}]+))/m,
+    inside: {
+      'parent': {
+        pattern: /&/,
+        alias: 'important'
+      },
+      'placeholder': /%[-\w]+/,
+      'variable': /\$[-\w]+|#\{\$[-\w]+\}/
+    }
+  },
+  'property': {
+    pattern: /(?:[\w-]|\$[-\w]+|#\{\$[-\w]+\})+(?=\s*:)/,
+    inside: {
+      'variable': /\$[-\w]+|#\{\$[-\w]+\}/
+    }
+  }
+});
+
+Prism.languages.insertBefore('scss', 'atrule', {
+  'keyword': [
+    /@(?:if|else(?: if)?|for|each|while|import|extend|debug|warn|mixin|include|function|return|content)/i,
+    {
+      pattern: /( +)(?:from|through)(?= )/,
+      lookbehind: true
+    }
+  ]
+});
+
+Prism.languages.insertBefore('scss', 'important', {
+  // var and interpolated vars
+  'variable': /\$[-\w]+|#\{\$[-\w]+\}/
+});
+
+Prism.languages.insertBefore('scss', 'function', {
+  'placeholder': {
+    pattern: /%[-\w]+/,
+    alias: 'selector'
+  },
+  'statement': {
+    pattern: /\B!(?:default|optional)\b/i,
+    alias: 'keyword'
+  },
+  'boolean': /\b(?:true|false)\b/,
+  'null': {
+    pattern: /\bnull\b/,
+    alias: 'keyword'
+  },
+  'operator': {
+    pattern: /(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|or|not)(?=\s)/,
+    lookbehind: true
+  }
+});
+
+Prism.languages.scss['atrule'].inside.rest = Prism.languages.scss;
+
+(function (Prism) {
+
+  // CAREFUL!
+  // The following patterns are concatenated, so the group referenced by a back reference is non-obvious!
+
+  var strings = [
+    // normal string
+    // 1 capturing group
+    /(["'])(?:\\[\s\S]|\$\([^)]+\)|`[^`]+`|(?!\1)[^\\])*\1/.source,
+
+    // here doc
+    // 1 capturing group
+    /<<-?\s*(\w+?)\s*(?:\r?\n|\r)[\s\S]*?(?:\r?\n|\r)\2/.source,
+
+    // here doc quoted
+    // 2 capturing group
+    /<<-?\s*(["'])(\w+)\3\s*(?:\r?\n|\r)[\s\S]*?(?:\r?\n|\r)\4/.source
+  ].join('|');
+
+  Prism.languages['shell-session'] = {
+    'command': {
+      pattern: RegExp(/\$(?:[^\r\n'"<]|<<str>>)+/.source.replace(/<<str>>/g, strings)),
+      inside: {
+        'bash': {
+          pattern: /(\$\s*)[\s\S]+/,
+          lookbehind: true,
+          alias: 'language-bash',
+          inside: Prism.languages.bash
+        },
+        'sh': {
+          pattern: /^\$/,
+          alias: 'important'
+        }
+      }
+    },
+    'output': {
+      pattern: /.(?:.*(?:\r\n?|\n|.$))*/
+      // output highlighting?
+    }
+  };
+
+}(Prism));
+
+Prism.languages.sql = {
+  'comment': {
+    pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,
+    lookbehind: true
+  },
+  'variable': [
+    {
+      pattern: /@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,
+      greedy: true
+    },
+    /@[\w.$]+/
+  ],
+  'string': {
+    pattern: /(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,
+    greedy: true,
+    lookbehind: true
+  },
+  'function': /\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i, 
// Should we highlight user defined functions too?
+  'keyword': 
/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?:
 EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT
 
|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:_INSERT|COL)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURNS?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USE
 
R)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?:
 ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,
+  'boolean': /\b(?:TRUE|FALSE|NULL)\b/i,
+  'number': /\b0x[\da-f]+\b|\b\d+\.?\d*|\B\.\d+\b/i,
+  'operator': 
/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|IN|LIKE|NOT|OR|IS|DIV|REGEXP|RLIKE|SOUNDS 
LIKE|XOR)\b/i,
+  'punctuation': /[;[\]()`,.]/
+};
+
+Prism.languages.typescript = Prism.languages.extend('javascript', {
+  // From JavaScript Prism keyword list and TypeScript language spec: 
https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#221-reserved-words
+  'keyword': 
/\b(?:abstract|as|async|await|break|case|catch|class|const|constructor|continue|debugger|declare|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|is|keyof|let|module|namespace|new|null|of|package|private|protected|public|readonly|return|require|set|static|super|switch|this|throw|try|type|typeof|undefined|var|void|while|with|yield)\b/,
+  'builtin': /\b(?:string|Function|any|number|boolean|Array|symbol|console|Promise|unknown|never)\b/,
+});
+
+Prism.languages.ts = Prism.languages.typescript;
+
 Prism.languages.yaml = {
   'scalar': {
     pattern: /([\-:]\s*(?:![^\s]+)?[ \t]*[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)[^\r\n]+(?:\2[^\r\n]+)*)/,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]