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