text: // CodeMirror, copyright (c) by Marijn Haverbeke and others
  // Distributed under an MIT license: http://codemirror.net/LICENSE
  
  // CodeMirror, copyright (c) by Marijn Haverbeke and others
  // Distributed under an MIT license: http://codemirror.net/LICENSE
  
  (function(mod) {
    if (typeof exports == "object" && typeof module == "object") // CommonJS
      mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));
    else if (typeof define == "function" && define.amd) // AMD
      define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod);
    else // Plain browser env
      mod(CodeMirror);
  })(function(CodeMirror) {
    "use strict";
  
    var defaultTags = {
      script: [
        ["lang", /(javascript|babel)/i, "javascript"],
        ["type", /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i, "javascript"],
        ["type", /./, "text/plain"],
        [null, null, "javascript"]
      ],
      style:  [
        ["lang", /^css$/i, "css"],
        ["type", /^(text\/)?(x-)?(stylesheet|css)$/i, "css"],
        ["type", /./, "text/plain"],
        [null, null, "css"]
      ]
    };
  
    function maybeBackup(stream, pat, style) {
      var cur = stream.current(), close = cur.search(pat);
      if (close > -1) {
        stream.backUp(cur.length - close);
      } else if (cur.match(/<\/?$/)) {
        stream.backUp(cur.length);
        if (!stream.match(pat, false)) stream.match(cur);
      }
      return style;
    }
  
    var attrRegexpCache = {};
    function getAttrRegexp(attr) {
      var regexp = attrRegexpCache[attr];
      if (regexp) return regexp;
      return attrRegexpCache[attr] = new RegExp("\\s+" + attr + "\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*");
    }
  
    function getAttrValue(text, attr) {
      var match = text.match(getAttrRegexp(attr))
      return match ? /^\s*(.*?)\s*$/.exec(match[2])[1] : ""
    }
  
    function getTagRegexp(tagName, anchored) {
      return new RegExp((anchored ? "^" : "") + "<\/\s*" + tagName + "\s*>", "i");
    }
  
    function addTags(from, to) {
      for (var tag in from) {
        var dest = to[tag] || (to[tag] = []);
        var source = from[tag];
        for (var i = source.length - 1; i >= 0; i--)
          dest.unshift(source[i])
      }
    }
  
    function findMatchingMode(tagInfo, tagText) {
      for (var i = 0; i < tagInfo.length; i++) {
        var spec = tagInfo[i];
        if (!spec[0] || spec[1].test(getAttrValue(tagText, spec[0]))) return spec[2];
      }
    }
  
    CodeMirror.defineMode("htmlmixed", function (config, parserConfig) {
      var htmlMode = CodeMirror.getMode(config, {
        name: "xml",
        htmlMode: true,
        multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
        multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag
      });
  
      var tags = {};
      var configTags = parserConfig && parserConfig.tags, configScript = parserConfig && parserConfig.scriptTypes;
      addTags(defaultTags, tags);
      if (configTags) addTags(configTags, tags);
      if (configScript) for (var i = configScript.length - 1; i >= 0; i--)
        tags.script.unshift(["type", configScript[i].matches, configScript[i].mode])
  
      function html(stream, state) {
        var style = htmlMode.token(stream, state.htmlState), tag = /\btag\b/.test(style), tagName
        if (tag && !/[<>\s\/]/.test(stream.current()) &&
            (tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase()) &&
            tags.hasOwnProperty(tagName)) {
          state.inTag = tagName + " "
        } else if (state.inTag && tag && />$/.test(stream.current())) {
          var inTag = /^([\S]+) (.*)/.exec(state.inTag)
          state.inTag = null
          var modeSpec = stream.current() == ">" && findMatchingMode(tags[inTag[1]], inTag[2])
          var mode = CodeMirror.getMode(config, modeSpec)
          var endTagA = getTagRegexp(inTag[1], true), endTag = getTagRegexp(inTag[1], false);
          state.token = function (stream, state) {
            if (stream.match(endTagA, false)) {
              state.token = html;
              state.localState = state.localMode = null;
              return null;
            }
            return maybeBackup(stream, endTag, state.localMode.token(stream, state.localState));
          };
          state.localMode = mode;
          state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, ""));
        } else if (state.inTag) {
          state.inTag += stream.current()
          if (stream.eol()) state.inTag += " "
        }
        return style;
      };
  
      return {
        startState: function () {
          var state = CodeMirror.startState(htmlMode);
          return {token: html, inTag: null, localMode: null, localState: null, htmlState: state};
        },
  
        copyState: function (state) {
          var local;
          if (state.localState) {
            local = CodeMirror.copyState(state.localMode, state.localState);
          }
          return {token: state.token, inTag: state.inTag,
                  localMode: state.localMode, localState: local,
                  htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
        },
  
        token: function (stream, state) {
          return state.token(stream, state);
        },
  
        indent: function (state, textAfter, line) {
          if (!state.localMode || /^\s*<\//.test(textAfter))
            return htmlMode.indent(state.htmlState, textAfter);
          else if (state.localMode.indent)
            return state.localMode.indent(state.localState, textAfter, line);
          else
            return CodeMirror.Pass;
        },
  
        innerMode: function (state) {
          return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
        }
      };
    }, "xml", "javascript", "css");
  
    CodeMirror.defineMIME("text/html", "htmlmixed");
  });
  
  
  // CodeMirror, copyright (c) by Marijn Haverbeke and others
  // Distributed under an MIT license: http://codemirror.net/LICENSE
  
  (function(mod) {
    if (typeof exports == "object" && typeof module == "object") // CommonJS
      mod(require("../../lib/codemirror"));
    else if (typeof define == "function" && define.amd) // AMD
      define(["../../lib/codemirror"], mod);
    else // Plain browser env
      mod(CodeMirror);
  })(function(CodeMirror) {
  "use strict";
  
  var htmlConfig = {
    autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
                      'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
                      'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
                      'track': true, 'wbr': true, 'menuitem': true},
    implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
                       'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
                       'th': true, 'tr': true},
    contextGrabbers: {
      'dd': {'dd': true, 'dt': true},
      'dt': {'dd': true, 'dt': true},
      'li': {'li': true},
      'option': {'option': true, 'optgroup': true},
      'optgroup': {'optgroup': true},
      'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
            'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
            'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
            'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
            'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
      'rp': {'rp': true, 'rt': true},
      'rt': {'rp': true, 'rt': true},
      'tbody': {'tbody': true, 'tfoot': true},
      'td': {'td': true, 'th': true},
      'tfoot': {'tbody': true},
      'th': {'td': true, 'th': true},
      'thead': {'tbody': true, 'tfoot': true},
      'tr': {'tr': true}
    },
    doNotIndent: {"pre": true},
    allowUnquoted: true,
    allowMissing: true,
    caseFold: true
  }
  
  var xmlConfig = {
    autoSelfClosers: {},
    implicitlyClosed: {},
    contextGrabbers: {},
    doNotIndent: {},
    allowUnquoted: false,
    allowMissing: false,
    caseFold: false
  }
  
  CodeMirror.defineMode("xml", function(editorConf, config_) {
    var indentUnit = editorConf.indentUnit
    var config = {}
    var defaults = config_.htmlMode ? htmlConfig : xmlConfig
    for (var prop in defaults) config[prop] = defaults[prop]
    for (var prop in config_) config[prop] = config_[prop]
  
    // Return variables for tokenizers
    var type, setStyle;
  
    function inText(stream, state) {
      function chain(parser) {
        state.tokenize = parser;
        return parser(stream, state);
      }
  
      var ch = stream.next();
      if (ch == "<") {
        if (stream.eat("!")) {
          if (stream.eat("[")) {
            if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
            else return null;
          } else if (stream.match("--")) {
            return chain(inBlock("comment", "-->"));
          } else if (stream.match("DOCTYPE", true, true)) {
            stream.eatWhile(/[\w\._\-]/);
            return chain(doctype(1));
          } else {
            return null;
          }
        } else if (stream.eat("?")) {
          stream.eatWhile(/[\w\._\-]/);
          state.tokenize = inBlock("meta", "?>");
          return "meta";
        } else {
          type = stream.eat("/") ? "closeTag" : "openTag";
          state.tokenize = inTag;
          return "tag bracket";
        }
      } else if (ch == "&") {
        var ok;
        if (stream.eat("#")) {
          if (stream.eat("x")) {
            ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
          } else {
            ok = stream.eatWhile(/[\d]/) && stream.eat(";");
          }
        } else {
          ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
        }
        return ok ? "atom" : "error";
      } else {
        stream.eatWhile(/[^&<]/);
        return null;
      }
    }
    inText.isInText = true;
  
    function inTag(stream, state) {
      var ch = stream.next();
      if (ch == ">" || (ch == "/" && stream.eat(">"))) {
        state.tokenize = inText;
        type = ch == ">" ? "endTag" : "selfcloseTag";
        return "tag bracket";
      } else if (ch == "=") {
        type = "equals";
        return null;
      } else if (ch == "<") {
        state.tokenize = inText;
        state.state = baseState;
        state.tagName = state.tagStart = null;
        var next = state.tokenize(stream, state);
        return next ? next + " tag error" : "tag error";
      } else if (/[\'\"]/.test(ch)) {
        state.tokenize = inAttribute(ch);
        state.stringStartCol = stream.column();
        return state.tokenize(stream, state);
      } else {
        stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
        return "word";
      }
    }
  
    function inAttribute(quote) {
      var closure = function(stream, state) {
        while (!stream.eol()) {
          if (stream.next() == quote) {
            state.tokenize = inTag;
            break;
          }
        }
        return "string";
      };
      closure.isInAttribute = true;
      return closure;
    }
  
    function inBlock(style, terminator) {
      return function(stream, state) {
        while (!stream.eol()) {
          if (stream.match(terminator)) {
            state.tokenize = inText;
            break;
          }
          stream.next();
        }
        return style;
      };
    }
    function doctype(depth) {
      return function(stream, state) {
        var ch;
        while ((ch = stream.next()) != null) {
          if (ch == "<") {
            state.tokenize = doctype(depth + 1);
            return state.tokenize(stream, state);
          } else if (ch == ">") {
            if (depth == 1) {
              state.tokenize = inText;
              break;
            } else {
              state.tokenize = doctype(depth - 1);
              return state.tokenize(stream, state);
            }
          }
        }
        return "meta";
      };
    }
  
    function Context(state, tagName, startOfLine) {
      this.prev = state.context;
      this.tagName = tagName;
      this.indent = state.indented;
      this.startOfLine = startOfLine;
      if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
        this.noIndent = true;
    }
    function popContext(state) {
      if (state.context) state.context = state.context.prev;
    }
    function maybePopContext(state, nextTagName) {
      var parentTagName;
      while (true) {
        if (!state.context) {
          return;
        }
        parentTagName = state.context.tagName;
        if (!config.contextGrabbers.hasOwnProperty(parentTagName) ||
            !config.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
          return;
        }
        popContext(state);
      }
    }
  
    function baseState(type, stream, state) {
      if (type == "openTag") {
        state.tagStart = stream.column();
        return tagNameState;
      } else if (type == "closeTag") {
        return closeTagNameState;
      } else {
        return baseState;
      }
    }
    function tagNameState(type, stream, state) {
      if (type == "word") {
        state.tagName = stream.current();
        setStyle = "tag";
        return attrState;
      } else {
        setStyle = "error";
        return tagNameState;
      }
    }
    function closeTagNameState(type, stream, state) {
      if (type == "word") {
        var tagName = stream.current();
        if (state.context && state.context.tagName != tagName &&
            config.implicitlyClosed.hasOwnProperty(state.context.tagName))
          popContext(state);
        if ((state.context && state.context.tagName == tagName) || config.matchClosing === false) {
          setStyle = "tag";
          return closeState;
        } else {
          setStyle = "tag error";
          return closeStateErr;
        }
      } else {
        setStyle = "error";
        return closeStateErr;
      }
    }
  
    function closeState(type, _stream, state) {
      if (type != "endTag") {
        setStyle = "error";
        return closeState;
      }
      popContext(state);
      return baseState;
    }
    function closeStateErr(type, stream, state) {
      setStyle = "error";
      return closeState(type, stream, state);
    }
  
    function attrState(type, _stream, state) {
      if (type == "word") {
        setStyle = "attribute";
        return attrEqState;
      } else if (type == "endTag" || type == "selfcloseTag") {
        var tagName = state.tagName, tagStart = state.tagStart;
        state.tagName = state.tagStart = null;
        if (type == "selfcloseTag" ||
            config.autoSelfClosers.hasOwnProperty(tagName)) {
          maybePopContext(state, tagName);
        } else {
          maybePopContext(state, tagName);
          state.context = new Context(state, tagName, tagStart == state.indented);
        }
        return baseState;
      }
      setStyle = "error";
      return attrState;
    }
    function attrEqState(type, stream, state) {
      if (type == "equals") return attrValueState;
      if (!config.allowMissing) setStyle = "error";
      return attrState(type, stream, state);
    }
    function attrValueState(type, stream, state) {
      if (type == "string") return attrContinuedState;
      if (type == "word" && config.allowUnquoted) {setStyle = "string"; return attrState;}
      setStyle = "error";
      return attrState(type, stream, state);
    }
    function attrContinuedState(type, stream, state) {
      if (type == "string") return attrContinuedState;
      return attrState(type, stream, state);
    }
  
    return {
      startState: function(baseIndent) {
        var state = {tokenize: inText,
                     state: baseState,
                     indented: baseIndent || 0,
                     tagName: null, tagStart: null,
                     context: null}
        if (baseIndent != null) state.baseIndent = baseIndent
        return state
      },
  
      token: function(stream, state) {
        if (!state.tagName && stream.sol())
          state.indented = stream.indentation();
  
        if (stream.eatSpace()) return null;
        type = null;
        var style = state.tokenize(stream, state);
        if ((style || type) && style != "comment") {
          setStyle = null;
          state.state = state.state(type || style, stream, state);
          if (setStyle)
            style = setStyle == "error" ? style + " error" : setStyle;
        }
        return style;
      },
  
      indent: function(state, textAfter, fullLine) {
        var context = state.context;
        // Indent multi-line strings (e.g. css).
        if (state.tokenize.isInAttribute) {
          if (state.tagStart == state.indented)
            return state.stringStartCol + 1;
          else
            return state.indented + indentUnit;
        }
        if (context && context.noIndent) return CodeMirror.Pass;
        if (state.tokenize != inTag && state.tokenize != inText)
          return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
        // Indent the starts of attribute names.
        if (state.tagName) {
          if (config.multilineTagIndentPastTag !== false)
            return state.tagStart + state.tagName.length + 2;
          else
            return state.tagStart + indentUnit * (config.multilineTagIndentFactor || 1);
        }
        if (config.alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
        var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
        if (tagAfter && tagAfter[1]) { // Closing tag spotted
          while (context) {
            if (context.tagName == tagAfter[2]) {
              context = context.prev;
              break;
            } else if (config.implicitlyClosed.hasOwnProperty(context.tagName)) {
              context = context.prev;
            } else {
              break;
            }
          }
        } else if (tagAfter) { // Opening tag spotted
          while (context) {
            var grabbers = config.contextGrabbers[context.tagName];
            if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
              context = context.prev;
            else
              break;
          }
        }
        while (context && context.prev && !context.startOfLine)
          context = context.prev;
        if (context) return context.indent + indentUnit;
        else return state.baseIndent || 0;
      },
  
      electricInput: /<\/[\s\w:]+>$/,
      blockCommentStart: "<!--",
      blockCommentEnd: "-->",
  
      configuration: config.htmlMode ? "html" : "xml",
      helperType: config.htmlMode ? "html" : "xml",
  
      skipAttribute: function(state) {
        if (state.state == attrValueState)
          state.state = attrState
      }
    };
  });
  
  CodeMirror.defineMIME("text/xml", "xml");
  CodeMirror.defineMIME("application/xml", "xml");
  if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
    CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
  
  });
  
  
  // CodeMirror, copyright (c) by Marijn Haverbeke and others
  // Distributed under an MIT license: http://codemirror.net/LICENSE
  
  (function(mod) {
    if (typeof exports == "object" && typeof module == "object") // CommonJS
      mod(require("../../lib/codemirror"));
    else if (typeof define == "function" && define.amd) // AMD
      define(["../../lib/codemirror"], mod);
    else // Plain browser env
      mod(CodeMirror);
  })(function(CodeMirror) {
  "use strict";
  
  CodeMirror.defineMode("css", function(config, parserConfig) {
    var inline = parserConfig.inline
    if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
  
    var indentUnit = config.indentUnit,
        tokenHooks = parserConfig.tokenHooks,
        documentTypes = parserConfig.documentTypes || {},
        mediaTypes = parserConfig.mediaTypes || {},
        mediaFeatures = parserConfig.mediaFeatures || {},
        mediaValueKeywords = parserConfig.mediaValueKeywords || {},
        propertyKeywords = parserConfig.propertyKeywords || {},
        nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
        fontProperties = parserConfig.fontProperties || {},
        counterDescriptors = parserConfig.counterDescriptors || {},
        colorKeywords = parserConfig.colorKeywords || {},
        valueKeywords = parserConfig.valueKeywords || {},
        allowNested = parserConfig.allowNested,
        lineComment = parserConfig.lineComment,
        supportsAtComponent = parserConfig.supportsAtComponent === true;
  
    var type, override;
    function ret(style, tp) { type = tp; return style; }
  
    // Tokenizers
  
    function tokenBase(stream, state) {
      var ch = stream.next();
      if (tokenHooks[ch]) {
        var result = tokenHooks[ch](stream, state);
        if (result !== false) return result;
      }
      if (ch == "@") {
        stream.eatWhile(/[\w\\\-]/);
        return ret("def", stream.current());
      } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
        return ret(null, "compare");
      } else if (ch == "\"" || ch == "'") {
        state.tokenize = tokenString(ch);
        return state.tokenize(stream, state);
      } else if (ch == "#") {
        stream.eatWhile(/[\w\\\-]/);
        return ret("atom", "hash");
      } else if (ch == "!") {
        stream.match(/^\s*\w*/);
        return ret("keyword", "important");
      } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
        stream.eatWhile(/[\w.%]/);
        return ret("number", "unit");
      } else if (ch === "-") {
        if (/[\d.]/.test(stream.peek())) {
          stream.eatWhile(/[\w.%]/);
          return ret("number", "unit");
        } else if (stream.match(/^-[\w\\\-]+/)) {
          stream.eatWhile(/[\w\\\-]/);
          if (stream.match(/^\s*:/, false))
            return ret("variable-2", "variable-definition");
          return ret("variable-2", "variable");
        } else if (stream.match(/^\w+-/)) {
          return ret("meta", "meta");
        }
      } else if (/[,+>*\/]/.test(ch)) {
        return ret(null, "select-op");
      } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
        return ret("qualifier", "qualifier");
      } else if (/[:;{}\[\]\(\)]/.test(ch)) {
        return ret(null, ch);
      } else if ((ch == "u" && stream.match(/rl(-prefix)?\(/)) ||
                 (ch == "d" && stream.match("omain(")) ||
                 (ch == "r" && stream.match("egexp("))) {
        stream.backUp(1);
        state.tokenize = tokenParenthesized;
        return ret("property", "word");
      } else if (/[\w\\\-]/.test(ch)) {
        stream.eatWhile(/[\w\\\-]/);
        return ret("property", "word");
      } else {
        return ret(null, null);
      }
    }
  
    function tokenString(quote) {
      return function(stream, state) {
        var escaped = false, ch;
        while ((ch = stream.next()) != null) {
          if (ch == quote && !escaped) {
            if (quote == ")") stream.backUp(1);
            break;
          }
          escaped = !escaped && ch == "\\";
        }
        if (ch == quote || !escaped && quote != ")") state.tokenize = null;
        return ret("string", "string");
      };
    }
  
    function tokenParenthesized(stream, state) {
      stream.next(); // Must be '('
      if (!stream.match(/\s*[\"\')]/, false))
        state.tokenize = tokenString(")");
      else
        state.tokenize = null;
      return ret(null, "(");
    }
  
    // Context management
  
    function Context(type, indent, prev) {
      this.type = type;
      this.indent = indent;
      this.prev = prev;
    }
  
    function pushContext(state, stream, type, indent) {
      state.context = new Context(type, stream.indentation() + (indent === false ? 0 : indentUnit), state.context);
      return type;
    }
  
    function popContext(state) {
      if (state.context.prev)
        state.context = state.context.prev;
      return state.context.type;
    }
  
    function pass(type, stream, state) {
      return states[state.context.type](type, stream, state);
    }
    function popAndPass(type, stream, state, n) {
      for (var i = n || 1; i > 0; i--)
        state.context = state.context.prev;
      return pass(type, stream, state);
    }
  
    // Parser
  
    function wordAsValue(stream) {
      var word = stream.current().toLowerCase();
      if (valueKeywords.hasOwnProperty(word))
        override = "atom";
      else if (colorKeywords.hasOwnProperty(word))
        override = "keyword";
      else
        override = "variable";
    }
  
    var states = {};
  
    states.top = function(type, stream, state) {
      if (type == "{") {
        return pushContext(state, stream, "block");
      } else if (type == "}" && state.context.prev) {
        return popContext(state);
      } else if (supportsAtComponent && /@component/.test(type)) {
        return pushContext(state, stream, "atComponentBlock");
      } else if (/^@(-moz-)?document$/.test(type)) {
        return pushContext(state, stream, "documentTypes");
      } else if (/^@(media|supports|(-moz-)?document|import)$/.test(type)) {
        return pushContext(state, stream, "atBlock");
      } else if (/^@(font-face|counter-style)/.test(type)) {
        state.stateArg = type;
        return "restricted_atBlock_before";
      } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
        return "keyframes";
      } else if (type && type.charAt(0) == "@") {
        return pushContext(state, stream, "at");
      } else if (type == "hash") {
        override = "builtin";
      } else if (type == "word") {
        override = "tag";
      } else if (type == "variable-definition") {
        return "maybeprop";
      } else if (type == "interpolation") {
        return pushContext(state, stream, "interpolation");
      } else if (type == ":") {
        return "pseudo";
      } else if (allowNested && type == "(") {
        return pushContext(state, stream, "parens");
      }
      return state.context.type;
    };
  
    states.block = function(type, stream, state) {
      if (type == "word") {
        var word = stream.current().toLowerCase();
        if (propertyKeywords.hasOwnProperty(word)) {
          override = "property";
          return "maybeprop";
        } else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
          override = "string-2";
          return "maybeprop";
        } else if (allowNested) {
          override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
          return "block";
        } else {
          override += " error";
          return "maybeprop";
        }
      } else if (type == "meta") {
        return "block";
      } else if (!allowNested && (type == "hash" || type == "qualifier")) {
        override = "error";
        return "block";
      } else {
        return states.top(type, stream, state);
      }
    };
  
    states.maybeprop = function(type, stream, state) {
      if (type == ":") return pushContext(state, stream, "prop");
      return pass(type, stream, state);
    };
  
    states.prop = function(type, stream, state) {
      if (type == ";") return popContext(state);
      if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
      if (type == "}" || type == "{") return popAndPass(type, stream, state);
      if (type == "(") return pushContext(state, stream, "parens");
  
      if (type == "hash" && !/^#([0-9a-fA-f]{3,4}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/.test(stream.current())) {
        override += " error";
      } else if (type == "word") {
        wordAsValue(stream);
      } else if (type == "interpolation") {
        return pushContext(state, stream, "interpolation");
      }
      return "prop";
    };
  
    states.propBlock = function(type, _stream, state) {
      if (type == "}") return popContext(state);
      if (type == "word") { override = "property"; return "maybeprop"; }
      return state.context.type;
    };
  
    states.parens = function(type, stream, state) {
      if (type == "{" || type == "}") return popAndPass(type, stream, state);
      if (type == ")") return popContext(state);
      if (type == "(") return pushContext(state, stream, "parens");
      if (type == "interpolation") return pushContext(state, stream, "interpolation");
      if (type == "word") wordAsValue(stream);
      return "parens";
    };
  
    states.pseudo = function(type, stream, state) {
      if (type == "meta") return "pseudo";
  
      if (type == "word") {
        override = "variable-3";
        return state.context.type;
      }
      return pass(type, stream, state);
    };
  
    states.documentTypes = function(type, stream, state) {
      if (type == "word" && documentTypes.hasOwnProperty(stream.current())) {
        override = "tag";
        return state.context.type;
      } else {
        return states.atBlock(type, stream, state);
      }
    };
  
    states.atBlock = function(type, stream, state) {
      if (type == "(") return pushContext(state, stream, "atBlock_parens");
      if (type == "}" || type == ";") return popAndPass(type, stream, state);
      if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
  
      if (type == "interpolation") return pushContext(state, stream, "interpolation");
  
      if (type == "word") {
        var word = stream.current().toLowerCase();
        if (word == "only" || word == "not" || word == "and" || word == "or")
          override = "keyword";
        else if (mediaTypes.hasOwnProperty(word))
          override = "attribute";
        else if (mediaFeatures.hasOwnProperty(word))
          override = "property";
        else if (mediaValueKeywords.hasOwnProperty(word))
          override = "keyword";
        else if (propertyKeywords.hasOwnProperty(word))
          override = "property";
        else if (nonStandardPropertyKeywords.hasOwnProperty(word))
          override = "string-2";
        else if (valueKeywords.hasOwnProperty(word))
          override = "atom";
        else if (colorKeywords.hasOwnProperty(word))
          override = "keyword";
        else
          override = "error";
      }
      return state.context.type;
    };
  
    states.atComponentBlock = function(type, stream, state) {
      if (type == "}")
        return popAndPass(type, stream, state);
      if (type == "{")
        return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top", false);
      if (type == "word")
        override = "error";
      return state.context.type;
    };
  
    states.atBlock_parens = function(type, stream, state) {
      if (type == ")") return popContext(state);
      if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
      return states.atBlock(type, stream, state);
    };
  
    states.restricted_atBlock_before = function(type, stream, state) {
      if (type == "{")
        return pushContext(state, stream, "restricted_atBlock");
      if (type == "word" && state.stateArg == "@counter-style") {
        override = "variable";
        return "restricted_atBlock_before";
      }
      return pass(type, stream, state);
    };
  
    states.restricted_atBlock = function(type, stream, state) {
      if (type == "}") {
        state.stateArg = null;
        return popContext(state);
      }
      if (type == "word") {
        if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) ||
            (state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase())))
          override = "error";
        else
          override = "property";
        return "maybeprop";
      }
      return "restricted_atBlock";
    };
  
    states.keyframes = function(type, stream, state) {
      if (type == "word") { override = "variable"; return "keyframes"; }
      if (type == "{") return pushContext(state, stream, "top");
      return pass(type, stream, state);
    };
  
    states.at = function(type, stream, state) {
      if (type == ";") return popContext(state);
      if (type == "{" || type == "}") return popAndPass(type, stream, state);
      if (type == "word") override = "tag";
      else if (type == "hash") override = "builtin";
      return "at";
    };
  
    states.interpolation = function(type, stream, state) {
      if (type == "}") return popContext(state);
      if (type == "{" || type == ";") return popAndPass(type, stream, state);
      if (type == "word") override = "variable";
      else if (type != "variable" && type != "(" && type != ")") override = "error";
      return "interpolation";
    };
  
    return {
      startState: function(base) {
        return {tokenize: null,
                state: inline ? "block" : "top",
                stateArg: null,
                context: new Context(inline ? "block" : "top", base || 0, null)};
      },
  
      token: function(stream, state) {
        if (!state.tokenize && stream.eatSpace()) return null;
        var style = (state.tokenize || tokenBase)(stream, state);
        if (style && typeof style == "object") {
          type = style[1];
          style = style[0];
        }
        override = style;
        state.state = states[state.state](type, stream, state);
        return override;
      },
  
      indent: function(state, textAfter) {
        var cx = state.context, ch = textAfter && textAfter.charAt(0);
        var indent = cx.indent;
        if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
        if (cx.prev) {
          if (ch == "}" && (cx.type == "block" || cx.type == "top" ||
                            cx.type == "interpolation" || cx.type == "restricted_atBlock")) {
            // Resume indentation from parent context.
            cx = cx.prev;
            indent = cx.indent;
          } else if (ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
              ch == "{" && (cx.type == "at" || cx.type == "atBlock")) {
            // Dedent relative to current context.
            indent = Math.max(0, cx.indent - indentUnit);
          }
        }
        return indent;
      },
  
      electricChars: "}",
      blockCommentStart: "/*",
      blockCommentEnd: "*/",
      lineComment: lineComment,
      fold: "brace"
    };
  });
  
    function keySet(array) {
      var keys = {};
      for (var i = 0; i < array.length; ++i) {
        keys[array[i].toLowerCase()] = true;
      }
      return keys;
    }
  
    var documentTypes_ = [
      "domain", "regexp", "url", "url-prefix"
    ], documentTypes = keySet(documentTypes_);
  
    var mediaTypes_ = [
      "all", "aural", "braille", "handheld", "print", "projection", "screen",
      "tty", "tv", "embossed"
    ], mediaTypes = keySet(mediaTypes_);
  
    var mediaFeatures_ = [
      "width", "min-width", "max-width", "height", "min-height", "max-height",
      "device-width", "min-device-width", "max-device-width", "device-height",
      "min-device-height", "max-device-height", "aspect-ratio",
      "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
      "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
      "max-color", "color-index", "min-color-index", "max-color-index",
      "monochrome", "min-monochrome", "max-monochrome", "resolution",
      "min-resolution", "max-resolution", "scan", "grid", "orientation",
      "device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio",
      "pointer", "any-pointer", "hover", "any-hover"
    ], mediaFeatures = keySet(mediaFeatures_);
  
    var mediaValueKeywords_ = [
      "landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover",
      "interlace", "progressive"
    ], mediaValueKeywords = keySet(mediaValueKeywords_);
  
    var propertyKeywords_ = [
      "align-content", "align-items", "align-self", "alignment-adjust",
      "alignment-baseline", "anchor-point", "animation", "animation-delay",
      "animation-direction", "animation-duration", "animation-fill-mode",
      "animation-iteration-count", "animation-name", "animation-play-state",
      "animation-timing-function", "appearance", "azimuth", "backface-visibility",
      "background", "background-attachment", "background-blend-mode", "background-clip",
      "background-color", "background-image", "background-origin", "background-position",
      "background-repeat", "background-size", "baseline-shift", "binding",
      "bleed", "bookmark-label", "bookmark-level", "bookmark-state",
      "bookmark-target", "border", "border-bottom", "border-bottom-color",
      "border-bottom-left-radius", "border-bottom-right-radius",
      "border-bottom-style", "border-bottom-width", "border-collapse",
      "border-color", "border-image", "border-image-outset",
      "border-image-repeat", "border-image-slice", "border-image-source",
      "border-image-width", "border-left", "border-left-color",
      "border-left-style", "border-left-width", "border-radius", "border-right",
      "border-right-color", "border-right-style", "border-right-width",
      "border-spacing", "border-style", "border-top", "border-top-color",
      "border-top-left-radius", "border-top-right-radius", "border-top-style",
      "border-top-width", "border-width", "bottom", "box-decoration-break",
      "box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
      "caption-side", "caret-color", "clear", "clip", "color", "color-profile", "column-count",
      "column-fill", "column-gap", "column-rule", "column-rule-color",
      "column-rule-style", "column-rule-width", "column-span", "column-width",
      "columns", "content", "counter-increment", "counter-reset", "crop", "cue",
      "cue-after", "cue-before", "cursor", "direction", "display",
      "dominant-baseline", "drop-initial-after-adjust",
      "drop-initial-after-align", "drop-initial-before-adjust",
      "drop-initial-before-align", "drop-initial-size", "drop-initial-value",
      "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
      "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
      "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
      "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
      "font-stretch", "font-style", "font-synthesis", "font-variant",
      "font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
      "font-variant-ligatures", "font-variant-numeric", "font-variant-position",
      "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow",
      "grid-auto-rows", "grid-column", "grid-column-end", "grid-column-gap",
      "grid-column-start", "grid-gap", "grid-row", "grid-row-end", "grid-row-gap",
      "grid-row-start", "grid-template", "grid-template-areas", "grid-template-columns",
      "grid-template-rows", "hanging-punctuation", "height", "hyphens",
      "icon", "image-orientation", "image-rendering", "image-resolution",
      "inline-box-align", "justify-content", "justify-items", "justify-self", "left", "letter-spacing",
      "line-break", "line-height", "line-stacking", "line-stacking-ruby",
      "line-stacking-shift", "line-stacking-strategy", "list-style",
      "list-style-image", "list-style-position", "list-style-type", "margin",
      "margin-bottom", "margin-left", "margin-right", "margin-top",
      "marks", "marquee-direction", "marquee-loop",
      "marquee-play-count", "marquee-speed", "marquee-style", "max-height",
      "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
      "nav-left", "nav-right", "nav-up", "object-fit", "object-position",
      "opacity", "order", "orphans", "outline",
      "outline-color", "outline-offset", "outline-style", "outline-width",
      "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
      "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
      "page", "page-break-after", "page-break-before", "page-break-inside",
      "page-policy", "pause", "pause-after", "pause-before", "perspective",
      "perspective-origin", "pitch", "pitch-range", "place-content", "place-items", "place-self", "play-during", "position",
      "presentation-level", "punctuation-trim", "quotes", "region-break-after",
      "region-break-before", "region-break-inside", "region-fragment",
      "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
      "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
      "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin",
      "shape-outside", "size", "speak", "speak-as", "speak-header",
      "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
      "tab-size", "table-layout", "target", "target-name", "target-new",
      "target-position", "text-align", "text-align-last", "text-decoration",
      "text-decoration-color", "text-decoration-line", "text-decoration-skip",
      "text-decoration-style", "text-emphasis", "text-emphasis-color",
      "text-emphasis-position", "text-emphasis-style", "text-height",
      "text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow",
      "text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position",
      "text-wrap", "top", "transform", "transform-origin", "transform-style",
      "transition", "transition-delay", "transition-duration",
      "transition-property", "transition-timing-function", "unicode-bidi",
      "user-select", "vertical-align", "visibility", "voice-balance", "voice-duration",
      "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
      "voice-volume", "volume", "white-space", "widows", "width", "will-change", "word-break",
      "word-spacing", "word-wrap", "z-index",
      // SVG-specific
      "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
      "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
      "color-interpolation", "color-interpolation-filters",
      "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
      "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
      "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
      "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
      "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
      "glyph-orientation-vertical", "text-anchor", "writing-mode"
    ], propertyKeywords = keySet(propertyKeywords_);
  
    var nonStandardPropertyKeywords_ = [
      "scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
      "scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
      "scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside",
      "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
      "searchfield-results-decoration", "zoom"
    ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
  
    var fontProperties_ = [
      "font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
      "font-stretch", "font-weight", "font-style"
    ], fontProperties = keySet(fontProperties_);
  
    var counterDescriptors_ = [
      "additive-symbols", "fallback", "negative", "pad", "prefix", "range",
      "speak-as", "suffix", "symbols", "system"
    ], counterDescriptors = keySet(counterDescriptors_);
  
    var colorKeywords_ = [
      "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
      "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
      "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
      "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
      "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
      "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
      "darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
      "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
      "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
      "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
      "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
      "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
      "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
      "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
      "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
      "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
      "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
      "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
      "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
      "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
      "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
      "purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
      "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
      "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
      "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
      "whitesmoke", "yellow", "yellowgreen"
    ], colorKeywords = keySet(colorKeywords_);
  
    var valueKeywords_ = [
      "above", "absolute", "activeborder", "additive", "activecaption", "afar",
      "after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate",
      "always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
      "arabic-indic", "armenian", "asterisks", "attr", "auto", "auto-flow", "avoid", "avoid-column", "avoid-page",
      "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
      "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
      "both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel",
      "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
      "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
      "cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
      "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
      "col-resize", "collapse", "color", "color-burn", "color-dodge", "column", "column-reverse",
      "compact", "condensed", "contain", "content", "contents",
      "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop",
      "cross", "crosshair", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal",
      "decimal-leading-zero", "default", "default-button", "dense", "destination-atop",
      "destination-in", "destination-out", "destination-over", "devanagari", "difference",
      "disc", "discard", "disclosure-closed", "disclosure-open", "document",
      "dot-dash", "dot-dot-dash",
      "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
      "element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
      "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
      "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
      "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
      "ethiopic-halehame-gez", "ethiopic-halehame-om-et",
      "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
      "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
      "ethiopic-numeric", "ew-resize", "exclusion", "expanded", "extends", "extra-condensed",
      "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes",
      "forwards", "from", "geometricPrecision", "georgian", "graytext", "grid", "groove",
      "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew",
      "help", "hidden", "hide", "higher", "highlight", "highlighttext",
      "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "hue", "icon", "ignore",
      "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
      "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
      "inline-block", "inline-flex", "inline-grid", "inline-table", "inset", "inside", "intrinsic", "invert",
      "italic", "japanese-formal", "japanese-informal", "justify", "kannada",
      "katakana", "katakana-iroha", "keep-all", "khmer",
      "korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
      "landscape", "lao", "large", "larger", "left", "level", "lighter", "lighten",
      "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
      "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
      "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
      "lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "match", "matrix", "matrix3d",
      "media-controls-background", "media-current-time-display",
      "media-fullscreen-button", "media-mute-button", "media-play-button",
      "media-return-to-realtime-button", "media-rewind-button",
      "media-seek-back-button", "media-seek-forward-button", "media-slider",
      "media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
      "media-volume-slider-container", "media-volume-sliderthumb", "medium",
      "menu", "menulist", "menulist-button", "menulist-text",
      "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
      "mix", "mongolian", "monospace", "move", "multiple", "multiply", "myanmar", "n-resize",
      "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
      "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
      "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "opacity", "open-quote",
      "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
      "outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
      "painted", "page", "paused", "persian", "perspective", "plus-darker", "plus-lighter",
      "pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d",
      "progress", "push-button", "radial-gradient", "radio", "read-only",
      "read-write", "read-write-plaintext-only", "rectangle", "region",
      "relative", "repeat", "repeating-linear-gradient",
      "repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse",
      "rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY",
      "rotateZ", "round", "row", "row-resize", "row-reverse", "rtl", "run-in", "running",
      "s-resize", "sans-serif", "saturation", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen",
      "scroll", "scrollbar", "scroll-position", "se-resize", "searchfield",
      "searchfield-cancel-button", "searchfield-decoration",
      "searchfield-results-button", "searchfield-results-decoration", "self-start", "self-end",
      "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
      "simp-chinese-formal", "simp-chinese-informal", "single",
      "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
      "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
      "small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali",
      "source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "space-evenly", "spell-out", "square",
      "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
      "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "system-ui", "table",
      "table-caption", "table-cell", "table-column", "table-column-group",
      "table-footer-group", "table-header-group", "table-row", "table-row-group",
      "tamil",
      "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
      "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
      "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
      "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
      "trad-chinese-formal", "trad-chinese-informal", "transform",
      "translate", "translate3d", "translateX", "translateY", "translateZ",
      "transparent", "ultra-condensed", "ultra-expanded", "underline", "unset", "up",
      "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
      "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
      "var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
      "visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
      "window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor",
      "xx-large", "xx-small"
    ], valueKeywords = keySet(valueKeywords_);
  
    var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(mediaValueKeywords_)
      .concat(propertyKeywords_).concat(nonStandardPropertyKeywords_).concat(colorKeywords_)
      .concat(valueKeywords_);
    CodeMirror.registerHelper("hintWords", "css", allWords);
  
    function tokenCComment(stream, state) {
      var maybeEnd = false, ch;
      while ((ch = stream.next()) != null) {
        if (maybeEnd && ch == "/") {
          state.tokenize = null;
          break;
        }
        maybeEnd = (ch == "*");
      }
      return ["comment", "comment"];
    }
  
    CodeMirror.defineMIME("text/css", {
      documentTypes: documentTypes,
      mediaTypes: mediaTypes,
      mediaFeatures: mediaFeatures,
      mediaValueKeywords: mediaValueKeywords,
      propertyKeywords: propertyKeywords,
      nonStandardPropertyKeywords: nonStandardPropertyKeywords,
      fontProperties: fontProperties,
      counterDescriptors: counterDescriptors,
      colorKeywords: colorKeywords,
      valueKeywords: valueKeywords,
      tokenHooks: {
        "/": function(stream, state) {
          if (!stream.eat("*")) return false;
          state.tokenize = tokenCComment;
          return tokenCComment(stream, state);
        }
      },
      name: "css"
    });
  
    CodeMirror.defineMIME("text/x-scss", {
      mediaTypes: mediaTypes,
      mediaFeatures: mediaFeatures,
      mediaValueKeywords: mediaValueKeywords,
      propertyKeywords: propertyKeywords,
      nonStandardPropertyKeywords: nonStandardPropertyKeywords,
      colorKeywords: colorKeywords,
      valueKeywords: valueKeywords,
      fontProperties: fontProperties,
      allowNested: true,
      lineComment: "//",
      tokenHooks: {
        "/": function(stream, state) {
          if (stream.eat("/")) {
            stream.skipToEnd();
            return ["comment", "comment"];
          } else if (stream.eat("*")) {
            state.tokenize = tokenCComment;
            return tokenCComment(stream, state);
          } else {
            return ["operator", "operator"];
          }
        },
        ":": function(stream) {
          if (stream.match(/\s*\{/, false))
            return [null, null]
          return false;
        },
        "$": function(stream) {
          stream.match(/^[\w-]+/);
          if (stream.match(/^\s*:/, false))
            return ["variable-2", "variable-definition"];
          return ["variable-2", "variable"];
        },
        "#": function(stream) {
          if (!stream.eat("{")) return false;
          return [null, "interpolation"];
        }
      },
      name: "css",
      helperType: "scss"
    });
  
    CodeMirror.defineMIME("text/x-less", {
      mediaTypes: mediaTypes,
      mediaFeatures: mediaFeatures,
      mediaValueKeywords: mediaValueKeywords,
      propertyKeywords: propertyKeywords,
      nonStandardPropertyKeywords: nonStandardPropertyKeywords,
      colorKeywords: colorKeywords,
      valueKeywords: valueKeywords,
      fontProperties: fontProperties,
      allowNested: true,
      lineComment: "//",
      tokenHooks: {
        "/": function(stream, state) {
          if (stream.eat("/")) {
            stream.skipToEnd();
            return ["comment", "comment"];
          } else if (stream.eat("*")) {
            state.tokenize = tokenCComment;
            return tokenCComment(stream, state);
          } else {
            return ["operator", "operator"];
          }
        },
        "@": function(stream) {
          if (stream.eat("{")) return [null, "interpolation"];
          if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false;
          stream.eatWhile(/[\w\\\-]/);
          if (stream.match(/^\s*:/, false))
            return ["variable-2", "variable-definition"];
          return ["variable-2", "variable"];
        },
        "&": function() {
          return ["atom", "atom"];
        }
      },
      name: "css",
      helperType: "less"
    });
  
    CodeMirror.defineMIME("text/x-gss", {
      documentTypes: documentTypes,
      mediaTypes: mediaTypes,
      mediaFeatures: mediaFeatures,
      propertyKeywords: propertyKeywords,
      nonStandardPropertyKeywords: nonStandardPropertyKeywords,
      fontProperties: fontProperties,
      counterDescriptors: counterDescriptors,
      colorKeywords: colorKeywords,
      valueKeywords: valueKeywords,
      supportsAtComponent: true,
      tokenHooks: {
        "/": function(stream, state) {
          if (!stream.eat("*")) return false;
          state.tokenize = tokenCComment;
          return tokenCComment(stream, state);
        }
      },
      name: "css",
      helperType: "gss"
    });
  
  });
  
  
  // CodeMirror, copyright (c) by Marijn Haverbeke and others
  // Distributed under an MIT license: http://codemirror.net/LICENSE
  
  (function(mod) {
    if (typeof exports == "object" && typeof module == "object") // CommonJS
      mod(require("../../lib/codemirror"));
    else if (typeof define == "function" && define.amd) // AMD
      define(["../../lib/codemirror"], mod);
    else // Plain browser env
      mod(CodeMirror);
  })(function(CodeMirror) {
  "use strict";
  
  function Context(indented, column, type, info, align, prev) {
    this.indented = indented;
    this.column = column;
    this.type = type;
    this.info = info;
    this.align = align;
    this.prev = prev;
  }
  function pushContext(state, col, type, info) {
    var indent = state.indented;
    if (state.context && state.context.type == "statement" && type != "statement")
      indent = state.context.indented;
    return state.context = new Context(indent, col, type, info, null, state.context);
  }
  function popContext(state) {
    var t = state.context.type;
    if (t == ")" || t == "]" || t == "}")
      state.indented = state.context.indented;
    return state.context = state.context.prev;
  }
  
  function typeBefore(stream, state, pos) {
    if (state.prevToken == "variable" || state.prevToken == "variable-3") return true;
    if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, pos))) return true;
    if (state.typeAtEndOfLine && stream.column() == stream.indentation()) return true;
  }
  
  function isTopScope(context) {
    for (;;) {
      if (!context || context.type == "top") return true;
      if (context.type == "}" && context.prev.info != "namespace") return false;
      context = context.prev;
    }
  }
  
  CodeMirror.defineMode("clike", function(config, parserConfig) {
    var indentUnit = config.indentUnit,
        statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
        dontAlignCalls = parserConfig.dontAlignCalls,
        keywords = parserConfig.keywords || {},
        types = parserConfig.types || {},
        builtin = parserConfig.builtin || {},
        blockKeywords = parserConfig.blockKeywords || {},
        defKeywords = parserConfig.defKeywords || {},
        atoms = parserConfig.atoms || {},
        hooks = parserConfig.hooks || {},
        multiLineStrings = parserConfig.multiLineStrings,
        indentStatements = parserConfig.indentStatements !== false,
        indentSwitch = parserConfig.indentSwitch !== false,
        namespaceSeparator = parserConfig.namespaceSeparator,
        isPunctuationChar = parserConfig.isPunctuationChar || /[\[\]{}\(\),;\:\.]/,
        numberStart = parserConfig.numberStart || /[\d\.]/,
        number = parserConfig.number || /^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)(u|ll?|l|f)?/i,
        isOperatorChar = parserConfig.isOperatorChar || /[+\-*&%=<>!?|\/]/,
        isIdentifierChar = parserConfig.isIdentifierChar || /[\w\$_\xa1-\uffff]/;
  
    var curPunc, isDefKeyword;
  
    function tokenBase(stream, state) {
      var ch = stream.next();
      if (hooks[ch]) {
        var result = hooks[ch](stream, state);
        if (result !== false) return result;
      }
      if (ch == '"' || ch == "'") {
        state.tokenize = tokenString(ch);
        return state.tokenize(stream, state);
      }
      if (isPunctuationChar.test(ch)) {
        curPunc = ch;
        return null;
      }
      if (numberStart.test(ch)) {
        stream.backUp(1)
        if (stream.match(number)) return "number"
        stream.next()
      }
      if (ch == "/") {
        if (stream.eat("*")) {
          state.tokenize = tokenComment;
          return tokenComment(stream, state);
        }
        if (stream.eat("/")) {
          stream.skipToEnd();
          return "comment";
        }
      }
      if (isOperatorChar.test(ch)) {
        while (!stream.match(/^\/[\/*]/, false) && stream.eat(isOperatorChar)) {}
        return "operator";
      }
      stream.eatWhile(isIdentifierChar);
      if (namespaceSeparator) while (stream.match(namespaceSeparator))
        stream.eatWhile(isIdentifierChar);
  
      var cur = stream.current();
      if (contains(keywords, cur)) {
        if (contains(blockKeywords, cur)) curPunc = "newstatement";
        if (contains(defKeywords, cur)) isDefKeyword = true;
        return "keyword";
      }
      if (contains(types, cur)) return "variable-3";
      if (contains(builtin, cur)) {
        if (contains(blockKeywords, cur)) curPunc = "newstatement";
        return "builtin";
      }
      if (contains(atoms, cur)) return "atom";
      return "variable";
    }
  
    function tokenString(quote) {
      return function(stream, state) {
        var escaped = false, next, end = false;
        while ((next = stream.next()) != null) {
          if (next == quote && !escaped) {end = true; break;}
          escaped = !escaped && next == "\\";
        }
        if (end || !(escaped || multiLineStrings))
          state.tokenize = null;
        return "string";
      };
    }
  
    function tokenComment(stream, state) {
      var maybeEnd = false, ch;
      while (ch = stream.next()) {
        if (ch == "/" && maybeEnd) {
          state.tokenize = null;
          break;
        }
        maybeEnd = (ch == "*");
      }
      return "comment";
    }
  
    function maybeEOL(stream, state) {
      if (parserConfig.typeFirstDefinitions && stream.eol() && isTopScope(state.context))
        state.typeAtEndOfLine = typeBefore(stream, state, stream.pos)
    }
  
    // Interface
  
    return {
      startState: function(basecolumn) {
        return {
          tokenize: null,
          context: new Context((basecolumn || 0) - indentUnit, 0, "top", null, false),
          indented: 0,
          startOfLine: true,
          prevToken: null
        };
      },
  
      token: function(stream, state) {
        var ctx = state.context;
        if (stream.sol()) {
          if (ctx.align == null) ctx.align = false;
          state.indented = stream.indentation();
          state.startOfLine = true;
        }
        if (stream.eatSpace()) { maybeEOL(stream, state); return null; }
        curPunc = isDefKeyword = null;
        var style = (state.tokenize || tokenBase)(stream, state);
        if (style == "comment" || style == "meta") return style;
        if (ctx.align == null) ctx.align = true;
  
        if (curPunc == ";" || curPunc == ":" || (curPunc == "," && stream.match(/^\s*(?:\/\/.*)?$/, false)))
          while (state.context.type == "statement") popContext(state);
        else if (curPunc == "{") pushContext(state, stream.column(), "}");
        else if (curPunc == "[") pushContext(state, stream.column(), "]");
        else if (curPunc == "(") pushContext(state, stream.column(), ")");
        else if (curPunc == "}") {
          while (ctx.type == "statement") ctx = popContext(state);
          if (ctx.type == "}") ctx = popContext(state);
          while (ctx.type == "statement") ctx = popContext(state);
        }
        else if (curPunc == ctx.type) popContext(state);
        else if (indentStatements &&
                 (((ctx.type == "}" || ctx.type == "top") && curPunc != ";") ||
                  (ctx.type == "statement" && curPunc == "newstatement"))) {
          pushContext(state, stream.column(), "statement", stream.current());
        }
  
        if (style == "variable" &&
            ((state.prevToken == "def" ||
              (parserConfig.typeFirstDefinitions && typeBefore(stream, state, stream.start) &&
               isTopScope(state.context) && stream.match(/^\s*\(/, false)))))
          style = "def";
  
        if (hooks.token) {
          var result = hooks.token(stream, state, style);
          if (result !== undefined) style = result;
        }
  
        if (style == "def" && parserConfig.styleDefs === false) style = "variable";
  
        state.startOfLine = false;
        state.prevToken = isDefKeyword ? "def" : style || curPunc;
        maybeEOL(stream, state);
        return style;
      },
  
      indent: function(state, textAfter) {
        if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine) return CodeMirror.Pass;
        var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
        if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
        if (parserConfig.dontIndentStatements)
          while (ctx.type == "statement" && parserConfig.dontIndentStatements.test(ctx.info))
            ctx = ctx.prev
        if (hooks.indent) {
          var hook = hooks.indent(state, ctx, textAfter);
          if (typeof hook == "number") return hook
        }
        var closing = firstChar == ctx.type;
        var switchBlock = ctx.prev && ctx.prev.info == "switch";
        if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) {
          while (ctx.type != "top" && ctx.type != "}") ctx = ctx.prev
          return ctx.indented
        }
        if (ctx.type == "statement")
          return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
        if (ctx.align && (!dontAlignCalls || ctx.type != ")"))
          return ctx.column + (closing ? 0 : 1);
        if (ctx.type == ")" && !closing)
          return ctx.indented + statementIndentUnit;
  
        return ctx.indented + (closing ? 0 : indentUnit) +
          (!closing && switchBlock && !/^(?:case|default)\b/.test(textAfter) ? indentUnit : 0);
      },
  
      electricInput: indentSwitch ? /^\s*(?:case .*?:|default:|\{\}?|\})$/ : /^\s*[{}]$/,
      blockCommentStart: "/*",
      blockCommentEnd: "*/",
      lineComment: "//",
      fold: "brace"
    };
  });
  
    function words(str) {
      var obj = {}, words = str.split(" ");
      for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
      return obj;
    }
    function contains(words, word) {
      if (typeof words === "function") {
        return words(word);
      } else {
        return words.propertyIsEnumerable(word);
      }
    }
    var cKeywords = "auto if break case register continue return default do sizeof " +
      "static else struct switch extern typedef union for goto while enum const volatile";
    var cTypes = "int long char short double float unsigned signed void size_t ptrdiff_t";
  
    function cppHook(stream, state) {
      if (!state.startOfLine) return false
      for (var ch, next = null; ch = stream.peek();) {
        if (ch == "\\" && stream.match(/^.$/)) {
          next = cppHook
          break
        } else if (ch == "/" && stream.match(/^\/[\/\*]/, false)) {
          break
        }
        stream.next()
      }
      state.tokenize = next
      return "meta"
    }
  
    function pointerHook(_stream, state) {
      if (state.prevToken == "variable-3") return "variable-3";
      return false;
    }
  
    function cpp14Literal(stream) {
      stream.eatWhile(/[\w\.']/);
      return "number";
    }
  
    function cpp11StringHook(stream, state) {
      stream.backUp(1);
      // Raw strings.
      if (stream.match(/(R|u8R|uR|UR|LR)/)) {
        var match = stream.match(/"([^\s\\()]{0,16})\(/);
        if (!match) {
          return false;
        }
        state.cpp11RawStringDelim = match[1];
        state.tokenize = tokenRawString;
        return tokenRawString(stream, state);
      }
      // Unicode strings/chars.
      if (stream.match(/(u8|u|U|L)/)) {
        if (stream.match(/["']/, /* eat */ false)) {
          return "string";
        }
        return false;
      }
      // Ignore this hook.
      stream.next();
      return false;
    }
  
    function cppLooksLikeConstructor(word) {
      var lastTwo = /(\w+)::~?(\w+)$/.exec(word);
      return lastTwo && lastTwo[1] == lastTwo[2];
    }
  
    // C#-style strings where "" escapes a quote.
    function tokenAtString(stream, state) {
      var next;
      while ((next = stream.next()) != null) {
        if (next == '"' && !stream.eat('"')) {
          state.tokenize = null;
          break;
        }
      }
      return "string";
    }
  
    // C++11 raw string literal is <prefix>"<delim>( anything )<delim>", where
    // <delim> can be a string up to 16 characters long.
    function tokenRawString(stream, state) {
      // Escape characters that have special regex meanings.
      var delim = state.cpp11RawStringDelim.replace(/[^\w\s]/g, '\\$&');
      var match = stream.match(new RegExp(".*?\\)" + delim + '"'));
      if (match)
        state.tokenize = null;
      else
        stream.skipToEnd();
      return "string";
    }
  
    function def(mimes, mode) {
      if (typeof mimes == "string") mimes = [mimes];
      var words = [];
      function add(obj) {
        if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))
          words.push(prop);
      }
      add(mode.keywords);
      add(mode.types);
      add(mode.builtin);
      add(mode.atoms);
      if (words.length) {
        mode.helperType = mimes[0];
        CodeMirror.registerHelper("hintWords", mimes[0], words);
      }
  
      for (var i = 0; i < mimes.length; ++i)
        CodeMirror.defineMIME(mimes[i], mode);
    }
  
    def(["text/x-csrc", "text/x-c", "text/x-chdr"], {
      name: "clike",
      keywords: words(cKeywords),
      types: words(cTypes + " bool _Complex _Bool float_t double_t intptr_t intmax_t " +
                   "int8_t int16_t int32_t int64_t uintptr_t uintmax_t uint8_t uint16_t " +
                   "uint32_t uint64_t"),
      blockKeywords: words("case do else for if switch while struct"),
      defKeywords: words("struct"),
      typeFirstDefinitions: true,
      atoms: words("null true false"),
      hooks: {"#": cppHook, "*": pointerHook},
      modeProps: {fold: ["brace", "include"]}
    });
  
    def(["text/x-c++src", "text/x-c++hdr"], {
      name: "clike",
      keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try explicit new " +
                      "static_cast typeid catch operator template typename class friend private " +
                      "this using const_cast inline public throw virtual delete mutable protected " +
                      "alignas alignof constexpr decltype nullptr noexcept thread_local final " +
                      "static_assert override"),
      types: words(cTypes + " bool wchar_t"),
      blockKeywords: words("catch class do else finally for if struct switch try while"),
      defKeywords: words("class namespace struct enum union"),
      typeFirstDefinitions: true,
      atoms: words("true false null"),
      dontIndentStatements: /^template$/,
      isIdentifierChar: /[\w\$_~\xa1-\uffff]/,
      hooks: {
        "#": cppHook,
        "*": pointerHook,
        "u": cpp11StringHook,
        "U": cpp11StringHook,
        "L": cpp11StringHook,
        "R": cpp11StringHook,
        "0": cpp14Literal,
        "1": cpp14Literal,
        "2": cpp14Literal,
        "3": cpp14Literal,
        "4": cpp14Literal,
        "5": cpp14Literal,
        "6": cpp14Literal,
        "7": cpp14Literal,
        "8": cpp14Literal,
        "9": cpp14Literal,
        token: function(stream, state, style) {
          if (style == "variable" && stream.peek() == "(" &&
              (state.prevToken == ";" || state.prevToken == null ||
               state.prevToken == "}") &&
              cppLooksLikeConstructor(stream.current()))
            return "def";
        }
      },
      namespaceSeparator: "::",
      modeProps: {fold: ["brace", "include"]}
    });
  
    def("text/x-java", {
      name: "clike",
      keywords: words("abstract assert break case catch class const continue default " +
                      "do else enum extends final finally float for goto if implements import " +
                      "instanceof interface native new package private protected public " +
                      "return static strictfp super switch synchronized this throw throws transient " +
                      "try volatile while @interface"),
      types: words("byte short int long float double boolean char void Boolean Byte Character Double Float " +
                   "Integer Long Number Object Short String StringBuffer StringBuilder Void"),
      blockKeywords: words("catch class do else finally for if switch try while"),
      defKeywords: words("class interface package enum @interface"),
      typeFirstDefinitions: true,
      atoms: words("true false null"),
      number: /^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+\.?\d*|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,
      hooks: {
        "@": function(stream) {
          // Don't match the @interface keyword.
          if (stream.match('interface', false)) return false;
  
          stream.eatWhile(/[\w\$_]/);
          return "meta";
        }
      },
      modeProps: {fold: ["brace", "import"]}
    });
  
    def("text/x-csharp", {
      name: "clike",
      keywords: words("abstract as async await base break case catch checked class const continue" +
                      " default delegate do else enum event explicit extern finally fixed for" +
                      " foreach goto if implicit in interface internal is lock namespace new" +
                      " operator out override params private protected public readonly ref return sealed" +
                      " sizeof stackalloc static struct switch this throw try typeof unchecked" +
                      " unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
                      " global group into join let orderby partial remove select set value var yield"),
      types: words("Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func" +
                   " Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32" +
                   " UInt64 bool byte char decimal double short int long object"  +
                   " sbyte float string ushort uint ulong"),
      blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
      defKeywords: words("class interface namespace struct var"),
      typeFirstDefinitions: true,
      atoms: words("true false null"),
      hooks: {
        "@": function(stream, state) {
          if (stream.eat('"')) {
            state.tokenize = tokenAtString;
            return tokenAtString(stream, state);
          }
          stream.eatWhile(/[\w\$_]/);
          return "meta";
        }
      }
    });
  
    function tokenTripleString(stream, state) {
      var escaped = false;
      while (!stream.eol()) {
        if (!escaped && stream.match('"""')) {
          state.tokenize = null;
          break;
        }
        escaped = stream.next() == "\\" && !escaped;
      }
      return "string";
    }
  
    def("text/x-scala", {
      name: "clike",
      keywords: words(
  
        /* scala */
        "abstract case catch class def do else extends final finally for forSome if " +
        "implicit import lazy match new null object override package private protected return " +
        "sealed super this throw trait try type val var while with yield _ " +
  
        /* package scala */
        "assert assume require print println printf readLine readBoolean readByte readShort " +
        "readChar readInt readLong readFloat readDouble"
      ),
      types: words(
        "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
        "Enumeration Equiv Error Exception Fractional Function IndexedSeq Int Integral Iterable " +
        "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
        "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
        "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector " +
  
        /* package java.lang */
        "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
        "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
        "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
        "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
      ),
      multiLineStrings: true,
      blockKeywords: words("catch class do else finally for forSome if match switch try while"),
      defKeywords: words("class def object package trait type val var"),
      atoms: words("true false null"),
      indentStatements: false,
      indentSwitch: false,
      isOperatorChar: /[+\-*&%=<>!?|\/#:@]/,
      hooks: {
        "@": function(stream) {
          stream.eatWhile(/[\w\$_]/);
          return "meta";
        },
        '"': function(stream, state) {
          if (!stream.match('""')) return false;
          state.tokenize = tokenTripleString;
          return state.tokenize(stream, state);
        },
        "'": function(stream) {
          stream.eatWhile(/[\w\$_\xa1-\uffff]/);
          return "atom";
        },
        "=": function(stream, state) {
          var cx = state.context
          if (cx.type == "}" && cx.align && stream.eat(">")) {
            state.context = new Context(cx.indented, cx.column, cx.type, cx.info, null, cx.prev)
            return "operator"
          } else {
            return false
          }
        }
      },
      modeProps: {closeBrackets: {triples: '"'}}
    });
  
    function tokenKotlinString(tripleString){
      return function (stream, state) {
        var escaped = false, next, end = false;
        while (!stream.eol()) {
          if (!tripleString && !escaped && stream.match('"') ) {end = true; break;}
          if (tripleString && stream.match('"""')) {end = true; break;}
          next = stream.next();
          if(!escaped && next == "$" && stream.match('{'))
            stream.skipTo("}");
          escaped = !escaped && next == "\\" && !tripleString;
        }
        if (end || !tripleString)
          state.tokenize = null;
        return "string";
      }
    }
  
    def("text/x-kotlin", {
      name: "clike",
      keywords: words(
        /*keywords*/
        "package as typealias class interface this super val " +
        "var fun for is in This throw return " +
        "break continue object if else while do try when !in !is as? " +
  
        /*soft keywords*/
        "file import where by get set abstract enum open inner override private public internal " +
        "protected catch finally out final vararg reified dynamic companion constructor init " +
        "sealed field property receiver param sparam lateinit data inline noinline tailrec " +
        "external annotation crossinline const operator infix suspend"
      ),
      types: words(
        /* package java.lang */
        "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
        "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
        "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
        "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
      ),
      intendSwitch: false,
      indentStatements: false,
      multiLineStrings: true,
      number: /^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+\.?\d*|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,
      blockKeywords: words("catch class do else finally for if where try while enum"),
      defKeywords: words("class val var object package interface fun"),
      atoms: words("true false null this"),
      hooks: {
        '"': function(stream, state) {
          state.tokenize = tokenKotlinString(stream.match('""'));
          return state.tokenize(stream, state);
        }
      },
      modeProps: {closeBrackets: {triples: '"'}}
    });
  
    def(["x-shader/x-vertex", "x-shader/x-fragment"], {
      name: "clike",
      keywords: words("sampler1D sampler2D sampler3D samplerCube " +
                      "sampler1DShadow sampler2DShadow " +
                      "const attribute uniform varying " +
                      "break continue discard return " +
                      "for while do if else struct " +
                      "in out inout"),
      types: words("float int bool void " +
                   "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
                   "mat2 mat3 mat4"),
      blockKeywords: words("for while do if else struct"),
      builtin: words("radians degrees sin cos tan asin acos atan " +
                      "pow exp log exp2 sqrt inversesqrt " +
                      "abs sign floor ceil fract mod min max clamp mix step smoothstep " +
                      "length distance dot cross normalize ftransform faceforward " +
                      "reflect refract matrixCompMult " +
                      "lessThan lessThanEqual greaterThan greaterThanEqual " +
                      "equal notEqual any all not " +
                      "texture1D texture1DProj texture1DLod texture1DProjLod " +
                      "texture2D texture2DProj texture2DLod texture2DProjLod " +
                      "texture3D texture3DProj texture3DLod texture3DProjLod " +
                      "textureCube textureCubeLod " +
                      "shadow1D shadow2D shadow1DProj shadow2DProj " +
                      "shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod " +
                      "dFdx dFdy fwidth " +
                      "noise1 noise2 noise3 noise4"),
      atoms: words("true false " +
                  "gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " +
                  "gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " +
                  "gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " +
                  "gl_FogCoord gl_PointCoord " +
                  "gl_Position gl_PointSize gl_ClipVertex " +
                  "gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " +
                  "gl_TexCoord gl_FogFragCoord " +
                  "gl_FragCoord gl_FrontFacing " +
                  "gl_FragData gl_FragDepth " +
                  "gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " +
                  "gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " +
                  "gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " +
                  "gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " +
                  "gl_ProjectionMatrixInverseTranspose " +
                  "gl_ModelViewProjectionMatrixInverseTranspose " +
                  "gl_TextureMatrixInverseTranspose " +
                  "gl_NormalScale gl_DepthRange gl_ClipPlane " +
                  "gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel " +
                  "gl_FrontLightModelProduct gl_BackLightModelProduct " +
                  "gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ " +
                  "gl_FogParameters " +
                  "gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords " +
                  "gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats " +
                  "gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
                  "gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
                  "gl_MaxDrawBuffers"),
      indentSwitch: false,
      hooks: {"#": cppHook},
      modeProps: {fold: ["brace", "include"]}
    });
  
    def("text/x-nesc", {
      name: "clike",
      keywords: words(cKeywords + "as atomic async call command component components configuration event generic " +
                      "implementation includes interface module new norace nx_struct nx_union post provides " +
                      "signal task uses abstract extends"),
      types: words(cTypes),
      blockKeywords: words("case do else for if switch while struct"),
      atoms: words("null true false"),
      hooks: {"#": cppHook},
      modeProps: {fold: ["brace", "include"]}
    });
  
    def("text/x-objectivec", {
      name: "clike",
      keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginary BOOL Class bycopy byref id IMP in " +
                      "inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),
      types: words(cTypes),
      atoms: words("YES NO NULL NILL ON OFF true false"),
      hooks: {
        "@": function(stream) {
          stream.eatWhile(/[\w\$]/);
          return "keyword";
        },
        "#": cppHook,
        indent: function(_state, ctx, textAfter) {
          if (ctx.type == "statement" && /^@\w/.test(textAfter)) return ctx.indented
        }
      },
      modeProps: {fold: "brace"}
    });
  
    def("text/x-squirrel", {
      name: "clike",
      keywords: words("base break clone continue const default delete enum extends function in class" +
                      " foreach local resume return this throw typeof yield constructor instanceof static"),
      types: words(cTypes),
      blockKeywords: words("case catch class else for foreach if switch try while"),
      defKeywords: words("function local class"),
      typeFirstDefinitions: true,
      atoms: words("true false null"),
      hooks: {"#": cppHook},
      modeProps: {fold: ["brace", "include"]}
    });
  
    // Ceylon Strings need to deal with interpolation
    var stringTokenizer = null;
    function tokenCeylonString(type) {
      return function(stream, state) {
        var escaped = false, next, end = false;
        while (!stream.eol()) {
          if (!escaped && stream.match('"') &&
                (type == "single" || stream.match('""'))) {
            end = true;
            break;
          }
          if (!escaped && stream.match('``')) {
            stringTokenizer = tokenCeylonString(type);
            end = true;
            break;
          }
          next = stream.next();
          escaped = type == "single" && !escaped && next == "\\";
        }
        if (end)
            state.tokenize = null;
        return "string";
      }
    }
  
    def("text/x-ceylon", {
      name: "clike",
      keywords: words("abstracts alias assembly assert assign break case catch class continue dynamic else" +
                      " exists extends finally for function given if import in interface is let module new" +
                      " nonempty object of out outer package return satisfies super switch then this throw" +
                      " try value void while"),
      types: function(word) {
          // In Ceylon all identifiers that start with an uppercase are types
          var first = word.charAt(0);
          return (first === first.toUpperCase() && first !== first.toLowerCase());
      },
      blockKeywords: words("case catch class dynamic else finally for function if interface module new object switch try while"),
      defKeywords: words("class dynamic function interface module object package value"),
      builtin: words("abstract actual aliased annotation by default deprecated doc final formal late license" +
                     " native optional sealed see serializable shared suppressWarnings tagged throws variable"),
      isPunctuationChar: /[\[\]{}\(\),;\:\.`]/,
      isOperatorChar: /[+\-*&%=<>!?|^~:\/]/,
      numberStart: /[\d#$]/,
      number: /^(?:#[\da-fA-F_]+|\$[01_]+|[\d_]+[kMGTPmunpf]?|[\d_]+\.[\d_]+(?:[eE][-+]?\d+|[kMGTPmunpf]|)|)/i,
      multiLineStrings: true,
      typeFirstDefinitions: true,
      atoms: words("true false null larger smaller equal empty finished"),
      indentSwitch: false,
      styleDefs: false,
      hooks: {
        "@": function(stream) {
          stream.eatWhile(/[\w\$_]/);
          return "meta";
        },
        '"': function(stream, state) {
            state.tokenize = tokenCeylonString(stream.match('""') ? "triple" : "single");
            return state.tokenize(stream, state);
          },
        '`': function(stream, state) {
            if (!stringTokenizer || !stream.match('`')) return false;
            state.tokenize = stringTokenizer;
            stringTokenizer = null;
            return state.tokenize(stream, state);
          },
        "'": function(stream) {
          stream.eatWhile(/[\w\$_\xa1-\uffff]/);
          return "atom";
        },
        token: function(_stream, state, style) {
            if ((style == "variable" || style == "variable-3") &&
                state.prevToken == ".") {
              return "variable-2";
            }
          }
      },
      modeProps: {
          fold: ["brace", "import"],
          closeBrackets: {triples: '"'}
      }
    });
  
  });
  
  
  
  (function(mod) {
    if (typeof exports == "object" && typeof module == "object") // CommonJS
      mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../clike/clike"));
    else if (typeof define == "function" && define.amd) // AMD
      define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../clike/clike"], mod);
    else // Plain browser env
      mod(CodeMirror);
  })(function(CodeMirror) {
    "use strict";
  
    function keywords(str) {
      var obj = {}, words = str.split(" ");
      for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
      return obj;
    }
  
    // Helper for phpString
    function matchSequence(list, end, escapes) {
      if (list.length == 0) return phpString(end);
      return function (stream, state) {
        var patterns = list[0];
        for (var i = 0; i < patterns.length; i++) if (stream.match(patterns[i][0])) {
          state.tokenize = matchSequence(list.slice(1), end);
          return patterns[i][1];
        }
        state.tokenize = phpString(end, escapes);
        return "string";
      };
    }
    function phpString(closing, escapes) {
      return function(stream, state) { return phpString_(stream, state, closing, escapes); };
    }
    function phpString_(stream, state, closing, escapes) {
      // "Complex" syntax
      if (escapes !== false && stream.match("${", false) || stream.match("{$", false)) {
        state.tokenize = null;
        return "string";
      }
  
      // Simple syntax
      if (escapes !== false && stream.match(/^\$[a-zA-Z_][a-zA-Z0-9_]*/)) {
        // After the variable name there may appear array or object operator.
        if (stream.match("[", false)) {
          // Match array operator
          state.tokenize = matchSequence([
            [["[", null]],
            [[/\d[\w\.]*/, "number"],
             [/\$[a-zA-Z_][a-zA-Z0-9_]*/, "variable-2"],
             [/[\w\$]+/, "variable"]],
            [["]", null]]
          ], closing, escapes);
        }
        if (stream.match(/\-\>\w/, false)) {
          // Match object operator
          state.tokenize = matchSequence([
            [["->", null]],
            [[/[\w]+/, "variable"]]
          ], closing, escapes);
        }
        return "variable-2";
      }
  
      var escaped = false;
      // Normal string
      while (!stream.eol() &&
             (escaped || escapes === false ||
              (!stream.match("{$", false) &&
               !stream.match(/^(\$[a-zA-Z_][a-zA-Z0-9_]*|\$\{)/, false)))) {
        if (!escaped && stream.match(closing)) {
          state.tokenize = null;
          state.tokStack.pop(); state.tokStack.pop();
          break;
        }
        escaped = stream.next() == "\\" && !escaped;
      }
      return "string";
    }
  
    var phpKeywords = "abstract and array as break case catch class clone const continue declare default " +
      "do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final " +
      "for foreach function global goto if implements interface instanceof namespace " +
      "new or private protected public static switch throw trait try use var while xor " +
      "die echo empty exit eval include include_once isset list require require_once return " +
      "print unset __halt_compiler self static parent yield insteadof finally";
    var phpAtoms = "true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__";
    var phpBuiltin = "func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents file_put_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists array_intersect_key array_combine array_column pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once json_decode json_encode json_last_error json_last_error_msg curl_close curl_copy_handle curl_errno curl_error curl_escape curl_exec curl_file_create curl_getinfo curl_init curl_multi_add_handle curl_multi_close curl_multi_exec curl_multi_getcontent curl_multi_info_read curl_multi_init curl_multi_remove_handle curl_multi_select curl_multi_setopt curl_multi_strerror curl_pause curl_reset curl_setopt_array curl_setopt curl_share_close curl_share_init curl_share_setopt curl_strerror curl_unescape curl_version mysqli_affected_rows mysqli_autocommit mysqli_change_user mysqli_character_set_name mysqli_close mysqli_commit mysqli_connect_errno mysqli_connect_error mysqli_connect mysqli_data_seek mysqli_debug mysqli_dump_debug_info mysqli_errno mysqli_error_list mysqli_error mysqli_fetch_all mysqli_fetch_array mysqli_fetch_assoc mysqli_fetch_field_direct mysqli_fetch_field mysqli_fetch_fields mysqli_fetch_lengths mysqli_fetch_object mysqli_fetch_row mysqli_field_count mysqli_field_seek mysqli_field_tell mysqli_free_result mysqli_get_charset mysqli_get_client_info mysqli_get_client_stats mysqli_get_client_version mysqli_get_connection_stats mysqli_get_host_info mysqli_get_proto_info mysqli_get_server_info mysqli_get_server_version mysqli_info mysqli_init mysqli_insert_id mysqli_kill mysqli_more_results mysqli_multi_query mysqli_next_result mysqli_num_fields mysqli_num_rows mysqli_options mysqli_ping mysqli_prepare mysqli_query mysqli_real_connect mysqli_real_escape_string mysqli_real_query mysqli_reap_async_query mysqli_refresh mysqli_rollback mysqli_select_db mysqli_set_charset mysqli_set_local_infile_default mysqli_set_local_infile_handler mysqli_sqlstate mysqli_ssl_set mysqli_stat mysqli_stmt_init mysqli_store_result mysqli_thread_id mysqli_thread_safe mysqli_use_result mysqli_warning_count";
    CodeMirror.registerHelper("hintWords", "php", [phpKeywords, phpAtoms, phpBuiltin].join(" ").split(" "));
    CodeMirror.registerHelper("wordChars", "php", /[\w$]/);
  
    var phpConfig = {
      name: "clike",
      helperType: "php",
      keywords: keywords(phpKeywords),
      blockKeywords: keywords("catch do else elseif for foreach if switch try while finally"),
      defKeywords: keywords("class function interface namespace trait"),
      atoms: keywords(phpAtoms),
      builtin: keywords(phpBuiltin),
      multiLineStrings: true,
      hooks: {
        "$": function(stream) {
          stream.eatWhile(/[\w\$_]/);
          return "variable-2";
        },
        "<": function(stream, state) {
          var before;
          if (before = stream.match(/<<\s*/)) {
            var quoted = stream.eat(/['"]/);
            stream.eatWhile(/[\w\.]/);
            var delim = stream.current().slice(before[0].length + (quoted ? 2 : 1));
            if (quoted) stream.eat(quoted);
            if (delim) {
              (state.tokStack || (state.tokStack = [])).push(delim, 0);
              state.tokenize = phpString(delim, quoted != "'");
              return "string";
            }
          }
          return false;
        },
        "#": function(stream) {
          while (!stream.eol() && !stream.match("?>", false)) stream.next();
          return "comment";
        },
        "/": function(stream) {
          if (stream.eat("/")) {
            while (!stream.eol() && !stream.match("?>", false)) stream.next();
            return "comment";
          }
          return false;
        },
        '"': function(_stream, state) {
          (state.tokStack || (state.tokStack = [])).push('"', 0);
          state.tokenize = phpString('"');
          return "string";
        },
        "{": function(_stream, state) {
          if (state.tokStack && state.tokStack.length)
            state.tokStack[state.tokStack.length - 1]++;
          return false;
        },
        "}": function(_stream, state) {
          if (state.tokStack && state.tokStack.length > 0 &&
              !--state.tokStack[state.tokStack.length - 1]) {
            state.tokenize = phpString(state.tokStack[state.tokStack.length - 2]);
          }
          return false;
        }
      }
    };
  
    CodeMirror.defineMode("php", function(config, parserConfig) {
      var htmlMode = CodeMirror.getMode(config, "text/html");
      var phpMode = CodeMirror.getMode(config, phpConfig);
  
      function dispatch(stream, state) {
        var isPHP = state.curMode == phpMode;
        if (stream.sol() && state.pending && state.pending != '"' && state.pending != "'") state.pending = null;
        if (!isPHP) {
          if (stream.match(/^<\?\w*/)) {
            state.curMode = phpMode;
            if (!state.php) state.php = CodeMirror.startState(phpMode, htmlMode.indent(state.html, ""))
            state.curState = state.php;
            return "meta";
          }
          if (state.pending == '"' || state.pending == "'") {
            while (!stream.eol() && stream.next() != state.pending) {}
            var style = "string";
          } else if (state.pending && stream.pos < state.pending.end) {
            stream.pos = state.pending.end;
            var style = state.pending.style;
          } else {
            var style = htmlMode.token(stream, state.curState);
          }
          if (state.pending) state.pending = null;
          var cur = stream.current(), openPHP = cur.search(/<\?/), m;
          if (openPHP != -1) {
            if (style == "string" && (m = cur.match(/[\'\"]$/)) && !/\?>/.test(cur)) state.pending = m[0];
            else state.pending = {end: stream.pos, style: style};
            stream.backUp(cur.length - openPHP);
          }
          return style;
        } else if (isPHP && state.php.tokenize == null && stream.match("?>")) {
          state.curMode = htmlMode;
          state.curState = state.html;
          if (!state.php.context.prev) state.php = null;
          return "meta";
        } else {
          return phpMode.token(stream, state.curState);
        }
      }
  
      return {
        startState: function() {
          var html = CodeMirror.startState(htmlMode)
          var php = parserConfig.startOpen ? CodeMirror.startState(phpMode) : null
          return {html: html,
                  php: php,
                  curMode: parserConfig.startOpen ? phpMode : htmlMode,
                  curState: parserConfig.startOpen ? php : html,
                  pending: null};
        },
  
        copyState: function(state) {
          var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html),
              php = state.php, phpNew = php && CodeMirror.copyState(phpMode, php), cur;
          if (state.curMode == htmlMode) cur = htmlNew;
          else cur = phpNew;
          return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,
                  pending: state.pending};
        },
  
        token: dispatch,
  
        indent: function(state, textAfter) {
          if ((state.curMode != phpMode && /^\s*<\//.test(textAfter)) ||
              (state.curMode == phpMode && /^\?>/.test(textAfter)))
            return htmlMode.indent(state.html, textAfter);
          return state.curMode.indent(state.curState, textAfter);
        },
  
        blockCommentStart: "/*",
        blockCommentEnd: "*/",
        lineComment: "//",
  
        innerMode: function(state) { return {state: state.curState, mode: state.curMode}; }
      };
    }, "htmlmixed", "clike");
  
    CodeMirror.defineMIME("application/x-httpd-php", "php");
    CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true});
    CodeMirror.defineMIME("text/x-php", phpConfig);
  });
  