github.com/elliott5/community@v0.14.1-0.20160709191136-823126fb026a/app/public/codemirror/mode/css/css.js (about)

     1  // CodeMirror, copyright (c) by Marijn Haverbeke and others
     2  // Distributed under an MIT license: http://codemirror.net/LICENSE
     3  
     4  (function(mod) {
     5    if (typeof exports == "object" && typeof module == "object") // CommonJS
     6      mod(require("../../lib/codemirror"));
     7    else if (typeof define == "function" && define.amd) // AMD
     8      define(["../../lib/codemirror"], mod);
     9    else // Plain browser env
    10      mod(CodeMirror);
    11  })(function(CodeMirror) {
    12  "use strict";
    13  
    14  CodeMirror.defineMode("css", function(config, parserConfig) {
    15    var inline = parserConfig.inline
    16    if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
    17  
    18    var indentUnit = config.indentUnit,
    19        tokenHooks = parserConfig.tokenHooks,
    20        documentTypes = parserConfig.documentTypes || {},
    21        mediaTypes = parserConfig.mediaTypes || {},
    22        mediaFeatures = parserConfig.mediaFeatures || {},
    23        mediaValueKeywords = parserConfig.mediaValueKeywords || {},
    24        propertyKeywords = parserConfig.propertyKeywords || {},
    25        nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
    26        fontProperties = parserConfig.fontProperties || {},
    27        counterDescriptors = parserConfig.counterDescriptors || {},
    28        colorKeywords = parserConfig.colorKeywords || {},
    29        valueKeywords = parserConfig.valueKeywords || {},
    30        allowNested = parserConfig.allowNested,
    31        supportsAtComponent = parserConfig.supportsAtComponent === true;
    32  
    33    var type, override;
    34    function ret(style, tp) { type = tp; return style; }
    35  
    36    // Tokenizers
    37  
    38    function tokenBase(stream, state) {
    39      var ch = stream.next();
    40      if (tokenHooks[ch]) {
    41        var result = tokenHooks[ch](stream, state);
    42        if (result !== false) return result;
    43      }
    44      if (ch == "@") {
    45        stream.eatWhile(/[\w\\\-]/);
    46        return ret("def", stream.current());
    47      } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
    48        return ret(null, "compare");
    49      } else if (ch == "\"" || ch == "'") {
    50        state.tokenize = tokenString(ch);
    51        return state.tokenize(stream, state);
    52      } else if (ch == "#") {
    53        stream.eatWhile(/[\w\\\-]/);
    54        return ret("atom", "hash");
    55      } else if (ch == "!") {
    56        stream.match(/^\s*\w*/);
    57        return ret("keyword", "important");
    58      } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
    59        stream.eatWhile(/[\w.%]/);
    60        return ret("number", "unit");
    61      } else if (ch === "-") {
    62        if (/[\d.]/.test(stream.peek())) {
    63          stream.eatWhile(/[\w.%]/);
    64          return ret("number", "unit");
    65        } else if (stream.match(/^-[\w\\\-]+/)) {
    66          stream.eatWhile(/[\w\\\-]/);
    67          if (stream.match(/^\s*:/, false))
    68            return ret("variable-2", "variable-definition");
    69          return ret("variable-2", "variable");
    70        } else if (stream.match(/^\w+-/)) {
    71          return ret("meta", "meta");
    72        }
    73      } else if (/[,+>*\/]/.test(ch)) {
    74        return ret(null, "select-op");
    75      } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
    76        return ret("qualifier", "qualifier");
    77      } else if (/[:;{}\[\]\(\)]/.test(ch)) {
    78        return ret(null, ch);
    79      } else if ((ch == "u" && stream.match(/rl(-prefix)?\(/)) ||
    80                 (ch == "d" && stream.match("omain(")) ||
    81                 (ch == "r" && stream.match("egexp("))) {
    82        stream.backUp(1);
    83        state.tokenize = tokenParenthesized;
    84        return ret("property", "word");
    85      } else if (/[\w\\\-]/.test(ch)) {
    86        stream.eatWhile(/[\w\\\-]/);
    87        return ret("property", "word");
    88      } else {
    89        return ret(null, null);
    90      }
    91    }
    92  
    93    function tokenString(quote) {
    94      return function(stream, state) {
    95        var escaped = false, ch;
    96        while ((ch = stream.next()) != null) {
    97          if (ch == quote && !escaped) {
    98            if (quote == ")") stream.backUp(1);
    99            break;
   100          }
   101          escaped = !escaped && ch == "\\";
   102        }
   103        if (ch == quote || !escaped && quote != ")") state.tokenize = null;
   104        return ret("string", "string");
   105      };
   106    }
   107  
   108    function tokenParenthesized(stream, state) {
   109      stream.next(); // Must be '('
   110      if (!stream.match(/\s*[\"\')]/, false))
   111        state.tokenize = tokenString(")");
   112      else
   113        state.tokenize = null;
   114      return ret(null, "(");
   115    }
   116  
   117    // Context management
   118  
   119    function Context(type, indent, prev) {
   120      this.type = type;
   121      this.indent = indent;
   122      this.prev = prev;
   123    }
   124  
   125    function pushContext(state, stream, type, indent) {
   126      state.context = new Context(type, stream.indentation() + (indent === false ? 0 : indentUnit), state.context);
   127      return type;
   128    }
   129  
   130    function popContext(state) {
   131      if (state.context.prev)
   132        state.context = state.context.prev;
   133      return state.context.type;
   134    }
   135  
   136    function pass(type, stream, state) {
   137      return states[state.context.type](type, stream, state);
   138    }
   139    function popAndPass(type, stream, state, n) {
   140      for (var i = n || 1; i > 0; i--)
   141        state.context = state.context.prev;
   142      return pass(type, stream, state);
   143    }
   144  
   145    // Parser
   146  
   147    function wordAsValue(stream) {
   148      var word = stream.current().toLowerCase();
   149      if (valueKeywords.hasOwnProperty(word))
   150        override = "atom";
   151      else if (colorKeywords.hasOwnProperty(word))
   152        override = "keyword";
   153      else
   154        override = "variable";
   155    }
   156  
   157    var states = {};
   158  
   159    states.top = function(type, stream, state) {
   160      if (type == "{") {
   161        return pushContext(state, stream, "block");
   162      } else if (type == "}" && state.context.prev) {
   163        return popContext(state);
   164      } else if (supportsAtComponent && /@component/.test(type)) {
   165        return pushContext(state, stream, "atComponentBlock");
   166      } else if (/^@(-moz-)?document$/.test(type)) {
   167        return pushContext(state, stream, "documentTypes");
   168      } else if (/^@(media|supports|(-moz-)?document|import)$/.test(type)) {
   169        return pushContext(state, stream, "atBlock");
   170      } else if (/^@(font-face|counter-style)/.test(type)) {
   171        state.stateArg = type;
   172        return "restricted_atBlock_before";
   173      } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
   174        return "keyframes";
   175      } else if (type && type.charAt(0) == "@") {
   176        return pushContext(state, stream, "at");
   177      } else if (type == "hash") {
   178        override = "builtin";
   179      } else if (type == "word") {
   180        override = "tag";
   181      } else if (type == "variable-definition") {
   182        return "maybeprop";
   183      } else if (type == "interpolation") {
   184        return pushContext(state, stream, "interpolation");
   185      } else if (type == ":") {
   186        return "pseudo";
   187      } else if (allowNested && type == "(") {
   188        return pushContext(state, stream, "parens");
   189      }
   190      return state.context.type;
   191    };
   192  
   193    states.block = function(type, stream, state) {
   194      if (type == "word") {
   195        var word = stream.current().toLowerCase();
   196        if (propertyKeywords.hasOwnProperty(word)) {
   197          override = "property";
   198          return "maybeprop";
   199        } else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
   200          override = "string-2";
   201          return "maybeprop";
   202        } else if (allowNested) {
   203          override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
   204          return "block";
   205        } else {
   206          override += " error";
   207          return "maybeprop";
   208        }
   209      } else if (type == "meta") {
   210        return "block";
   211      } else if (!allowNested && (type == "hash" || type == "qualifier")) {
   212        override = "error";
   213        return "block";
   214      } else {
   215        return states.top(type, stream, state);
   216      }
   217    };
   218  
   219    states.maybeprop = function(type, stream, state) {
   220      if (type == ":") return pushContext(state, stream, "prop");
   221      return pass(type, stream, state);
   222    };
   223  
   224    states.prop = function(type, stream, state) {
   225      if (type == ";") return popContext(state);
   226      if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
   227      if (type == "}" || type == "{") return popAndPass(type, stream, state);
   228      if (type == "(") return pushContext(state, stream, "parens");
   229  
   230      if (type == "hash" && !/^#([0-9a-fA-f]{3,4}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/.test(stream.current())) {
   231        override += " error";
   232      } else if (type == "word") {
   233        wordAsValue(stream);
   234      } else if (type == "interpolation") {
   235        return pushContext(state, stream, "interpolation");
   236      }
   237      return "prop";
   238    };
   239  
   240    states.propBlock = function(type, _stream, state) {
   241      if (type == "}") return popContext(state);
   242      if (type == "word") { override = "property"; return "maybeprop"; }
   243      return state.context.type;
   244    };
   245  
   246    states.parens = function(type, stream, state) {
   247      if (type == "{" || type == "}") return popAndPass(type, stream, state);
   248      if (type == ")") return popContext(state);
   249      if (type == "(") return pushContext(state, stream, "parens");
   250      if (type == "interpolation") return pushContext(state, stream, "interpolation");
   251      if (type == "word") wordAsValue(stream);
   252      return "parens";
   253    };
   254  
   255    states.pseudo = function(type, stream, state) {
   256      if (type == "word") {
   257        override = "variable-3";
   258        return state.context.type;
   259      }
   260      return pass(type, stream, state);
   261    };
   262  
   263    states.documentTypes = function(type, stream, state) {
   264      if (type == "word" && documentTypes.hasOwnProperty(stream.current())) {
   265        override = "tag";
   266        return state.context.type;
   267      } else {
   268        return states.atBlock(type, stream, state);
   269      }
   270    };
   271  
   272    states.atBlock = function(type, stream, state) {
   273      if (type == "(") return pushContext(state, stream, "atBlock_parens");
   274      if (type == "}" || type == ";") return popAndPass(type, stream, state);
   275      if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
   276  
   277      if (type == "interpolation") return pushContext(state, stream, "interpolation");
   278  
   279      if (type == "word") {
   280        var word = stream.current().toLowerCase();
   281        if (word == "only" || word == "not" || word == "and" || word == "or")
   282          override = "keyword";
   283        else if (mediaTypes.hasOwnProperty(word))
   284          override = "attribute";
   285        else if (mediaFeatures.hasOwnProperty(word))
   286          override = "property";
   287        else if (mediaValueKeywords.hasOwnProperty(word))
   288          override = "keyword";
   289        else if (propertyKeywords.hasOwnProperty(word))
   290          override = "property";
   291        else if (nonStandardPropertyKeywords.hasOwnProperty(word))
   292          override = "string-2";
   293        else if (valueKeywords.hasOwnProperty(word))
   294          override = "atom";
   295        else if (colorKeywords.hasOwnProperty(word))
   296          override = "keyword";
   297        else
   298          override = "error";
   299      }
   300      return state.context.type;
   301    };
   302  
   303    states.atComponentBlock = function(type, stream, state) {
   304      if (type == "}")
   305        return popAndPass(type, stream, state);
   306      if (type == "{")
   307        return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top", false);
   308      if (type == "word")
   309        override = "error";
   310      return state.context.type;
   311    };
   312  
   313    states.atBlock_parens = function(type, stream, state) {
   314      if (type == ")") return popContext(state);
   315      if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
   316      return states.atBlock(type, stream, state);
   317    };
   318  
   319    states.restricted_atBlock_before = function(type, stream, state) {
   320      if (type == "{")
   321        return pushContext(state, stream, "restricted_atBlock");
   322      if (type == "word" && state.stateArg == "@counter-style") {
   323        override = "variable";
   324        return "restricted_atBlock_before";
   325      }
   326      return pass(type, stream, state);
   327    };
   328  
   329    states.restricted_atBlock = function(type, stream, state) {
   330      if (type == "}") {
   331        state.stateArg = null;
   332        return popContext(state);
   333      }
   334      if (type == "word") {
   335        if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) ||
   336            (state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase())))
   337          override = "error";
   338        else
   339          override = "property";
   340        return "maybeprop";
   341      }
   342      return "restricted_atBlock";
   343    };
   344  
   345    states.keyframes = function(type, stream, state) {
   346      if (type == "word") { override = "variable"; return "keyframes"; }
   347      if (type == "{") return pushContext(state, stream, "top");
   348      return pass(type, stream, state);
   349    };
   350  
   351    states.at = function(type, stream, state) {
   352      if (type == ";") return popContext(state);
   353      if (type == "{" || type == "}") return popAndPass(type, stream, state);
   354      if (type == "word") override = "tag";
   355      else if (type == "hash") override = "builtin";
   356      return "at";
   357    };
   358  
   359    states.interpolation = function(type, stream, state) {
   360      if (type == "}") return popContext(state);
   361      if (type == "{" || type == ";") return popAndPass(type, stream, state);
   362      if (type == "word") override = "variable";
   363      else if (type != "variable" && type != "(" && type != ")") override = "error";
   364      return "interpolation";
   365    };
   366  
   367    return {
   368      startState: function(base) {
   369        return {tokenize: null,
   370                state: inline ? "block" : "top",
   371                stateArg: null,
   372                context: new Context(inline ? "block" : "top", base || 0, null)};
   373      },
   374  
   375      token: function(stream, state) {
   376        if (!state.tokenize && stream.eatSpace()) return null;
   377        var style = (state.tokenize || tokenBase)(stream, state);
   378        if (style && typeof style == "object") {
   379          type = style[1];
   380          style = style[0];
   381        }
   382        override = style;
   383        state.state = states[state.state](type, stream, state);
   384        return override;
   385      },
   386  
   387      indent: function(state, textAfter) {
   388        var cx = state.context, ch = textAfter && textAfter.charAt(0);
   389        var indent = cx.indent;
   390        if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
   391        if (cx.prev) {
   392          if (ch == "}" && (cx.type == "block" || cx.type == "top" ||
   393                            cx.type == "interpolation" || cx.type == "restricted_atBlock")) {
   394            // Resume indentation from parent context.
   395            cx = cx.prev;
   396            indent = cx.indent;
   397          } else if (ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
   398              ch == "{" && (cx.type == "at" || cx.type == "atBlock")) {
   399            // Dedent relative to current context.
   400            indent = Math.max(0, cx.indent - indentUnit);
   401            cx = cx.prev;
   402          }
   403        }
   404        return indent;
   405      },
   406  
   407      electricChars: "}",
   408      blockCommentStart: "/*",
   409      blockCommentEnd: "*/",
   410      fold: "brace"
   411    };
   412  });
   413  
   414    function keySet(array) {
   415      var keys = {};
   416      for (var i = 0; i < array.length; ++i) {
   417        keys[array[i]] = true;
   418      }
   419      return keys;
   420    }
   421  
   422    var documentTypes_ = [
   423      "domain", "regexp", "url", "url-prefix"
   424    ], documentTypes = keySet(documentTypes_);
   425  
   426    var mediaTypes_ = [
   427      "all", "aural", "braille", "handheld", "print", "projection", "screen",
   428      "tty", "tv", "embossed"
   429    ], mediaTypes = keySet(mediaTypes_);
   430  
   431    var mediaFeatures_ = [
   432      "width", "min-width", "max-width", "height", "min-height", "max-height",
   433      "device-width", "min-device-width", "max-device-width", "device-height",
   434      "min-device-height", "max-device-height", "aspect-ratio",
   435      "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
   436      "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
   437      "max-color", "color-index", "min-color-index", "max-color-index",
   438      "monochrome", "min-monochrome", "max-monochrome", "resolution",
   439      "min-resolution", "max-resolution", "scan", "grid", "orientation",
   440      "device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio",
   441      "pointer", "any-pointer", "hover", "any-hover"
   442    ], mediaFeatures = keySet(mediaFeatures_);
   443  
   444    var mediaValueKeywords_ = [
   445      "landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover",
   446      "interlace", "progressive"
   447    ], mediaValueKeywords = keySet(mediaValueKeywords_);
   448  
   449    var propertyKeywords_ = [
   450      "align-content", "align-items", "align-self", "alignment-adjust",
   451      "alignment-baseline", "anchor-point", "animation", "animation-delay",
   452      "animation-direction", "animation-duration", "animation-fill-mode",
   453      "animation-iteration-count", "animation-name", "animation-play-state",
   454      "animation-timing-function", "appearance", "azimuth", "backface-visibility",
   455      "background", "background-attachment", "background-clip", "background-color",
   456      "background-image", "background-origin", "background-position",
   457      "background-repeat", "background-size", "baseline-shift", "binding",
   458      "bleed", "bookmark-label", "bookmark-level", "bookmark-state",
   459      "bookmark-target", "border", "border-bottom", "border-bottom-color",
   460      "border-bottom-left-radius", "border-bottom-right-radius",
   461      "border-bottom-style", "border-bottom-width", "border-collapse",
   462      "border-color", "border-image", "border-image-outset",
   463      "border-image-repeat", "border-image-slice", "border-image-source",
   464      "border-image-width", "border-left", "border-left-color",
   465      "border-left-style", "border-left-width", "border-radius", "border-right",
   466      "border-right-color", "border-right-style", "border-right-width",
   467      "border-spacing", "border-style", "border-top", "border-top-color",
   468      "border-top-left-radius", "border-top-right-radius", "border-top-style",
   469      "border-top-width", "border-width", "bottom", "box-decoration-break",
   470      "box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
   471      "caption-side", "clear", "clip", "color", "color-profile", "column-count",
   472      "column-fill", "column-gap", "column-rule", "column-rule-color",
   473      "column-rule-style", "column-rule-width", "column-span", "column-width",
   474      "columns", "content", "counter-increment", "counter-reset", "crop", "cue",
   475      "cue-after", "cue-before", "cursor", "direction", "display",
   476      "dominant-baseline", "drop-initial-after-adjust",
   477      "drop-initial-after-align", "drop-initial-before-adjust",
   478      "drop-initial-before-align", "drop-initial-size", "drop-initial-value",
   479      "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
   480      "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
   481      "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
   482      "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
   483      "font-stretch", "font-style", "font-synthesis", "font-variant",
   484      "font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
   485      "font-variant-ligatures", "font-variant-numeric", "font-variant-position",
   486      "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow",
   487      "grid-auto-position", "grid-auto-rows", "grid-column", "grid-column-end",
   488      "grid-column-start", "grid-row", "grid-row-end", "grid-row-start",
   489      "grid-template", "grid-template-areas", "grid-template-columns",
   490      "grid-template-rows", "hanging-punctuation", "height", "hyphens",
   491      "icon", "image-orientation", "image-rendering", "image-resolution",
   492      "inline-box-align", "justify-content", "left", "letter-spacing",
   493      "line-break", "line-height", "line-stacking", "line-stacking-ruby",
   494      "line-stacking-shift", "line-stacking-strategy", "list-style",
   495      "list-style-image", "list-style-position", "list-style-type", "margin",
   496      "margin-bottom", "margin-left", "margin-right", "margin-top",
   497      "marker-offset", "marks", "marquee-direction", "marquee-loop",
   498      "marquee-play-count", "marquee-speed", "marquee-style", "max-height",
   499      "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
   500      "nav-left", "nav-right", "nav-up", "object-fit", "object-position",
   501      "opacity", "order", "orphans", "outline",
   502      "outline-color", "outline-offset", "outline-style", "outline-width",
   503      "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
   504      "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
   505      "page", "page-break-after", "page-break-before", "page-break-inside",
   506      "page-policy", "pause", "pause-after", "pause-before", "perspective",
   507      "perspective-origin", "pitch", "pitch-range", "play-during", "position",
   508      "presentation-level", "punctuation-trim", "quotes", "region-break-after",
   509      "region-break-before", "region-break-inside", "region-fragment",
   510      "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
   511      "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
   512      "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin",
   513      "shape-outside", "size", "speak", "speak-as", "speak-header",
   514      "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
   515      "tab-size", "table-layout", "target", "target-name", "target-new",
   516      "target-position", "text-align", "text-align-last", "text-decoration",
   517      "text-decoration-color", "text-decoration-line", "text-decoration-skip",
   518      "text-decoration-style", "text-emphasis", "text-emphasis-color",
   519      "text-emphasis-position", "text-emphasis-style", "text-height",
   520      "text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow",
   521      "text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position",
   522      "text-wrap", "top", "transform", "transform-origin", "transform-style",
   523      "transition", "transition-delay", "transition-duration",
   524      "transition-property", "transition-timing-function", "unicode-bidi",
   525      "vertical-align", "visibility", "voice-balance", "voice-duration",
   526      "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
   527      "voice-volume", "volume", "white-space", "widows", "width", "word-break",
   528      "word-spacing", "word-wrap", "z-index",
   529      // SVG-specific
   530      "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
   531      "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
   532      "color-interpolation", "color-interpolation-filters",
   533      "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
   534      "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
   535      "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
   536      "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
   537      "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
   538      "glyph-orientation-vertical", "text-anchor", "writing-mode"
   539    ], propertyKeywords = keySet(propertyKeywords_);
   540  
   541    var nonStandardPropertyKeywords_ = [
   542      "scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
   543      "scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
   544      "scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside",
   545      "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
   546      "searchfield-results-decoration", "zoom"
   547    ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
   548  
   549    var fontProperties_ = [
   550      "font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
   551      "font-stretch", "font-weight", "font-style"
   552    ], fontProperties = keySet(fontProperties_);
   553  
   554    var counterDescriptors_ = [
   555      "additive-symbols", "fallback", "negative", "pad", "prefix", "range",
   556      "speak-as", "suffix", "symbols", "system"
   557    ], counterDescriptors = keySet(counterDescriptors_);
   558  
   559    var colorKeywords_ = [
   560      "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
   561      "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
   562      "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
   563      "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
   564      "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
   565      "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
   566      "darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
   567      "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
   568      "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
   569      "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
   570      "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
   571      "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
   572      "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
   573      "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
   574      "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
   575      "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
   576      "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
   577      "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
   578      "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
   579      "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
   580      "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
   581      "purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
   582      "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
   583      "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
   584      "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
   585      "whitesmoke", "yellow", "yellowgreen"
   586    ], colorKeywords = keySet(colorKeywords_);
   587  
   588    var valueKeywords_ = [
   589      "above", "absolute", "activeborder", "additive", "activecaption", "afar",
   590      "after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate",
   591      "always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
   592      "arabic-indic", "armenian", "asterisks", "attr", "auto", "avoid", "avoid-column", "avoid-page",
   593      "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
   594      "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
   595      "both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel",
   596      "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
   597      "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
   598      "cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
   599      "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
   600      "col-resize", "collapse", "column", "column-reverse", "compact", "condensed", "contain", "content",
   601      "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop",
   602      "cross", "crosshair", "currentcolor", "cursive", "cyclic", "dashed", "decimal",
   603      "decimal-leading-zero", "default", "default-button", "destination-atop",
   604      "destination-in", "destination-out", "destination-over", "devanagari",
   605      "disc", "discard", "disclosure-closed", "disclosure-open", "document",
   606      "dot-dash", "dot-dot-dash",
   607      "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
   608      "element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
   609      "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
   610      "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
   611      "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
   612      "ethiopic-halehame-gez", "ethiopic-halehame-om-et",
   613      "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
   614      "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
   615      "ethiopic-numeric", "ew-resize", "expanded", "extends", "extra-condensed",
   616      "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes",
   617      "forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
   618      "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew",
   619      "help", "hidden", "hide", "higher", "highlight", "highlighttext",
   620      "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
   621      "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
   622      "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
   623      "inline-block", "inline-flex", "inline-table", "inset", "inside", "intrinsic", "invert",
   624      "italic", "japanese-formal", "japanese-informal", "justify", "kannada",
   625      "katakana", "katakana-iroha", "keep-all", "khmer",
   626      "korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
   627      "landscape", "lao", "large", "larger", "left", "level", "lighter",
   628      "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
   629      "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
   630      "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
   631      "lower-roman", "lowercase", "ltr", "malayalam", "match", "matrix", "matrix3d",
   632      "media-controls-background", "media-current-time-display",
   633      "media-fullscreen-button", "media-mute-button", "media-play-button",
   634      "media-return-to-realtime-button", "media-rewind-button",
   635      "media-seek-back-button", "media-seek-forward-button", "media-slider",
   636      "media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
   637      "media-volume-slider-container", "media-volume-sliderthumb", "medium",
   638      "menu", "menulist", "menulist-button", "menulist-text",
   639      "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
   640      "mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize",
   641      "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
   642      "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
   643      "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
   644      "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
   645      "outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
   646      "painted", "page", "paused", "persian", "perspective", "plus-darker", "plus-lighter",
   647      "pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d",
   648      "progress", "push-button", "radial-gradient", "radio", "read-only",
   649      "read-write", "read-write-plaintext-only", "rectangle", "region",
   650      "relative", "repeat", "repeating-linear-gradient",
   651      "repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse",
   652      "rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY",
   653      "rotateZ", "round", "row", "row-resize", "row-reverse", "rtl", "run-in", "running",
   654      "s-resize", "sans-serif", "scale", "scale3d", "scaleX", "scaleY", "scaleZ",
   655      "scroll", "scrollbar", "se-resize", "searchfield",
   656      "searchfield-cancel-button", "searchfield-decoration",
   657      "searchfield-results-button", "searchfield-results-decoration",
   658      "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
   659      "simp-chinese-formal", "simp-chinese-informal", "single",
   660      "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
   661      "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
   662      "small", "small-caps", "small-caption", "smaller", "solid", "somali",
   663      "source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "spell-out", "square",
   664      "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
   665      "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "table",
   666      "table-caption", "table-cell", "table-column", "table-column-group",
   667      "table-footer-group", "table-header-group", "table-row", "table-row-group",
   668      "tamil",
   669      "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
   670      "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
   671      "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
   672      "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
   673      "trad-chinese-formal", "trad-chinese-informal",
   674      "translate", "translate3d", "translateX", "translateY", "translateZ",
   675      "transparent", "ultra-condensed", "ultra-expanded", "underline", "up",
   676      "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
   677      "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
   678      "var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
   679      "visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
   680      "window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor",
   681      "xx-large", "xx-small"
   682    ], valueKeywords = keySet(valueKeywords_);
   683  
   684    var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(mediaValueKeywords_)
   685      .concat(propertyKeywords_).concat(nonStandardPropertyKeywords_).concat(colorKeywords_)
   686      .concat(valueKeywords_);
   687    CodeMirror.registerHelper("hintWords", "css", allWords);
   688  
   689    function tokenCComment(stream, state) {
   690      var maybeEnd = false, ch;
   691      while ((ch = stream.next()) != null) {
   692        if (maybeEnd && ch == "/") {
   693          state.tokenize = null;
   694          break;
   695        }
   696        maybeEnd = (ch == "*");
   697      }
   698      return ["comment", "comment"];
   699    }
   700  
   701    CodeMirror.defineMIME("text/css", {
   702      documentTypes: documentTypes,
   703      mediaTypes: mediaTypes,
   704      mediaFeatures: mediaFeatures,
   705      mediaValueKeywords: mediaValueKeywords,
   706      propertyKeywords: propertyKeywords,
   707      nonStandardPropertyKeywords: nonStandardPropertyKeywords,
   708      fontProperties: fontProperties,
   709      counterDescriptors: counterDescriptors,
   710      colorKeywords: colorKeywords,
   711      valueKeywords: valueKeywords,
   712      tokenHooks: {
   713        "/": function(stream, state) {
   714          if (!stream.eat("*")) return false;
   715          state.tokenize = tokenCComment;
   716          return tokenCComment(stream, state);
   717        }
   718      },
   719      name: "css"
   720    });
   721  
   722    CodeMirror.defineMIME("text/x-scss", {
   723      mediaTypes: mediaTypes,
   724      mediaFeatures: mediaFeatures,
   725      mediaValueKeywords: mediaValueKeywords,
   726      propertyKeywords: propertyKeywords,
   727      nonStandardPropertyKeywords: nonStandardPropertyKeywords,
   728      colorKeywords: colorKeywords,
   729      valueKeywords: valueKeywords,
   730      fontProperties: fontProperties,
   731      allowNested: true,
   732      tokenHooks: {
   733        "/": function(stream, state) {
   734          if (stream.eat("/")) {
   735            stream.skipToEnd();
   736            return ["comment", "comment"];
   737          } else if (stream.eat("*")) {
   738            state.tokenize = tokenCComment;
   739            return tokenCComment(stream, state);
   740          } else {
   741            return ["operator", "operator"];
   742          }
   743        },
   744        ":": function(stream) {
   745          if (stream.match(/\s*\{/))
   746            return [null, "{"];
   747          return false;
   748        },
   749        "$": function(stream) {
   750          stream.match(/^[\w-]+/);
   751          if (stream.match(/^\s*:/, false))
   752            return ["variable-2", "variable-definition"];
   753          return ["variable-2", "variable"];
   754        },
   755        "#": function(stream) {
   756          if (!stream.eat("{")) return false;
   757          return [null, "interpolation"];
   758        }
   759      },
   760      name: "css",
   761      helperType: "scss"
   762    });
   763  
   764    CodeMirror.defineMIME("text/x-less", {
   765      mediaTypes: mediaTypes,
   766      mediaFeatures: mediaFeatures,
   767      mediaValueKeywords: mediaValueKeywords,
   768      propertyKeywords: propertyKeywords,
   769      nonStandardPropertyKeywords: nonStandardPropertyKeywords,
   770      colorKeywords: colorKeywords,
   771      valueKeywords: valueKeywords,
   772      fontProperties: fontProperties,
   773      allowNested: true,
   774      tokenHooks: {
   775        "/": function(stream, state) {
   776          if (stream.eat("/")) {
   777            stream.skipToEnd();
   778            return ["comment", "comment"];
   779          } else if (stream.eat("*")) {
   780            state.tokenize = tokenCComment;
   781            return tokenCComment(stream, state);
   782          } else {
   783            return ["operator", "operator"];
   784          }
   785        },
   786        "@": function(stream) {
   787          if (stream.eat("{")) return [null, "interpolation"];
   788          if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false;
   789          stream.eatWhile(/[\w\\\-]/);
   790          if (stream.match(/^\s*:/, false))
   791            return ["variable-2", "variable-definition"];
   792          return ["variable-2", "variable"];
   793        },
   794        "&": function() {
   795          return ["atom", "atom"];
   796        }
   797      },
   798      name: "css",
   799      helperType: "less"
   800    });
   801  
   802    CodeMirror.defineMIME("text/x-gss", {
   803      documentTypes: documentTypes,
   804      mediaTypes: mediaTypes,
   805      mediaFeatures: mediaFeatures,
   806      propertyKeywords: propertyKeywords,
   807      nonStandardPropertyKeywords: nonStandardPropertyKeywords,
   808      fontProperties: fontProperties,
   809      counterDescriptors: counterDescriptors,
   810      colorKeywords: colorKeywords,
   811      valueKeywords: valueKeywords,
   812      supportsAtComponent: true,
   813      tokenHooks: {
   814        "/": function(stream, state) {
   815          if (!stream.eat("*")) return false;
   816          state.tokenize = tokenCComment;
   817          return tokenCComment(stream, state);
   818        }
   819      },
   820      name: "css",
   821      helperType: "gss"
   822    });
   823  
   824  });