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
14CodeMirror.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