codemirror-rails 5.0 → 5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +104 -64
  4. data/vendor/assets/javascripts/codemirror/addons/dialog/dialog.js +3 -1
  5. data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +144 -121
  6. data/vendor/assets/javascripts/codemirror/addons/fold/foldgutter.js +4 -2
  7. data/vendor/assets/javascripts/codemirror/addons/hint/css-hint.js +4 -0
  8. data/vendor/assets/javascripts/codemirror/addons/hint/sql-hint.js +13 -8
  9. data/vendor/assets/javascripts/codemirror/addons/lint/lint.js +2 -0
  10. data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +40 -0
  11. data/vendor/assets/javascripts/codemirror/addons/mode/multiplex_test.js +33 -0
  12. data/vendor/assets/javascripts/codemirror/addons/scroll/simplescrollbars.js +8 -2
  13. data/vendor/assets/javascripts/codemirror/addons/tern/tern.js +1 -1
  14. data/vendor/assets/javascripts/codemirror/keymaps/sublime.js +13 -0
  15. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +43 -54
  16. data/vendor/assets/javascripts/codemirror/modes/asciiarmor.js +73 -0
  17. data/vendor/assets/javascripts/codemirror/modes/clike.js +2 -1
  18. data/vendor/assets/javascripts/codemirror/modes/clojure.js +1 -0
  19. data/vendor/assets/javascripts/codemirror/modes/cmake.js +97 -0
  20. data/vendor/assets/javascripts/codemirror/modes/commonlisp.js +1 -0
  21. data/vendor/assets/javascripts/codemirror/modes/css.js +1 -0
  22. data/vendor/assets/javascripts/codemirror/modes/groovy.js +1 -0
  23. data/vendor/assets/javascripts/codemirror/modes/htmlembedded.js +18 -76
  24. data/vendor/assets/javascripts/codemirror/modes/javascript.js +5 -0
  25. data/vendor/assets/javascripts/codemirror/modes/kotlin.js +1 -0
  26. data/vendor/assets/javascripts/codemirror/modes/less_test.js +51 -0
  27. data/vendor/assets/javascripts/codemirror/modes/mllike.js +1 -1
  28. data/vendor/assets/javascripts/codemirror/modes/properties.js +1 -1
  29. data/vendor/assets/javascripts/codemirror/modes/python.js +1 -0
  30. data/vendor/assets/javascripts/codemirror/modes/sass.js +1 -1
  31. data/vendor/assets/javascripts/codemirror/modes/scheme.js +1 -0
  32. data/vendor/assets/javascripts/codemirror/modes/scss_test.js +110 -0
  33. data/vendor/assets/javascripts/codemirror/modes/smarty.js +100 -107
  34. data/vendor/assets/javascripts/codemirror/modes/stylus.js +651 -332
  35. data/vendor/assets/javascripts/codemirror/modes/test.js +67 -0
  36. data/vendor/assets/javascripts/codemirror/modes/troff.js +82 -0
  37. data/vendor/assets/javascripts/codemirror/modes/vb.js +6 -5
  38. data/vendor/assets/javascripts/codemirror/modes/verilog.js +53 -53
  39. data/vendor/assets/stylesheets/codemirror.css +11 -8
  40. data/vendor/assets/stylesheets/codemirror/themes/mdn-like.css +1 -1
  41. metadata +9 -3
  42. data/vendor/assets/javascripts/codemirror/modes/smartymixed.js +0 -197
@@ -13,134 +13,118 @@
13
13
  else // Plain browser env
14
14
  mod(CodeMirror);
15
15
  })(function(CodeMirror) {
16
- "use strict";
17
-
18
- CodeMirror.defineMode("smarty", function(config) {
19
16
  "use strict";
20
17
 
21
- // our default settings; check to see if they're overridden
22
- var settings = {
23
- rightDelimiter: '}',
24
- leftDelimiter: '{',
25
- smartyVersion: 2 // for backward compatibility
26
- };
27
- if (config.hasOwnProperty("leftDelimiter")) {
28
- settings.leftDelimiter = config.leftDelimiter;
29
- }
30
- if (config.hasOwnProperty("rightDelimiter")) {
31
- settings.rightDelimiter = config.rightDelimiter;
32
- }
33
- if (config.hasOwnProperty("smartyVersion") && config.smartyVersion === 3) {
34
- settings.smartyVersion = 3;
35
- }
36
-
37
- var keyFunctions = ["debug", "extends", "function", "include", "literal"];
38
- var last;
39
- var regs = {
40
- operatorChars: /[+\-*&%=<>!?]/,
41
- validIdentifier: /[a-zA-Z0-9_]/,
42
- stringChar: /['"]/
43
- };
44
-
45
- var helpers = {
46
- cont: function(style, lastType) {
18
+ CodeMirror.defineMode("smarty", function(config, parserConf) {
19
+ var rightDelimiter = parserConf.rightDelimiter || "}";
20
+ var leftDelimiter = parserConf.leftDelimiter || "{";
21
+ var version = parserConf.version || 2;
22
+ var baseMode = CodeMirror.getMode(config, parserConf.baseMode || "null");
23
+
24
+ var keyFunctions = ["debug", "extends", "function", "include", "literal"];
25
+ var regs = {
26
+ operatorChars: /[+\-*&%=<>!?]/,
27
+ validIdentifier: /[a-zA-Z0-9_]/,
28
+ stringChar: /['"]/
29
+ };
30
+
31
+ var last;
32
+ function cont(style, lastType) {
47
33
  last = lastType;
48
34
  return style;
49
- },
50
- chain: function(stream, state, parser) {
35
+ }
36
+
37
+ function chain(stream, state, parser) {
51
38
  state.tokenize = parser;
52
39
  return parser(stream, state);
53
40
  }
54
- };
55
41
 
42
+ // Smarty 3 allows { and } surrounded by whitespace to NOT slip into Smarty mode
43
+ function doesNotCount(stream, pos) {
44
+ if (pos == null) pos = stream.pos;
45
+ return version === 3 && leftDelimiter == "{" &&
46
+ (pos == stream.string.length || /\s/.test(stream.string.charAt(pos)));
47
+ }
56
48
 
57
- // our various parsers
58
- var parsers = {
59
-
60
- // the main tokenizer
61
- tokenizer: function(stream, state) {
62
- if (stream.match(settings.leftDelimiter, true)) {
49
+ function tokenTop(stream, state) {
50
+ if (stream.match(leftDelimiter, true)) {
63
51
  if (stream.eat("*")) {
64
- return helpers.chain(stream, state, parsers.inBlock("comment", "*" + settings.rightDelimiter));
65
- } else {
66
- // Smarty 3 allows { and } surrounded by whitespace to NOT slip into Smarty mode
52
+ return chain(stream, state, tokenBlock("comment", "*" + rightDelimiter));
53
+ } else if (!doesNotCount(stream)) {
67
54
  state.depth++;
68
- var isEol = stream.eol();
69
- var isFollowedByWhitespace = /\s/.test(stream.peek());
70
- if (settings.smartyVersion === 3 && settings.leftDelimiter === "{" && (isEol || isFollowedByWhitespace)) {
71
- state.depth--;
72
- return null;
73
- } else {
74
- state.tokenize = parsers.smarty;
75
- last = "startTag";
76
- return "tag";
77
- }
55
+ state.tokenize = tokenSmarty;
56
+ last = "startTag";
57
+ return "tag";
78
58
  }
79
- } else {
80
- stream.next();
81
- return null;
82
59
  }
83
- },
60
+
61
+ var token = baseMode.token(stream, state.base);
62
+ var text = stream.current();
63
+ var found = text.indexOf(leftDelimiter);
64
+ if (found > -1 && !doesNotCount(stream, stream.start + found + 1))
65
+ stream.backUp(text.length - found);
66
+ return token;
67
+ }
84
68
 
85
69
  // parsing Smarty content
86
- smarty: function(stream, state) {
87
- if (stream.match(settings.rightDelimiter, true)) {
88
- if (settings.smartyVersion === 3) {
70
+ function tokenSmarty(stream, state) {
71
+ if (stream.match(rightDelimiter, true)) {
72
+ if (version === 3) {
89
73
  state.depth--;
90
74
  if (state.depth <= 0) {
91
- state.tokenize = parsers.tokenizer;
75
+ state.tokenize = tokenTop;
92
76
  }
93
77
  } else {
94
- state.tokenize = parsers.tokenizer;
78
+ state.tokenize = tokenTop;
95
79
  }
96
- return helpers.cont("tag", null);
80
+ return cont("tag", null);
97
81
  }
98
82
 
99
- if (stream.match(settings.leftDelimiter, true)) {
83
+ if (stream.match(leftDelimiter, true)) {
100
84
  state.depth++;
101
- return helpers.cont("tag", "startTag");
85
+ return cont("tag", "startTag");
102
86
  }
103
87
 
104
88
  var ch = stream.next();
105
89
  if (ch == "$") {
106
90
  stream.eatWhile(regs.validIdentifier);
107
- return helpers.cont("variable-2", "variable");
91
+ return cont("variable-2", "variable");
108
92
  } else if (ch == "|") {
109
- return helpers.cont("operator", "pipe");
93
+ return cont("operator", "pipe");
110
94
  } else if (ch == ".") {
111
- return helpers.cont("operator", "property");
95
+ return cont("operator", "property");
112
96
  } else if (regs.stringChar.test(ch)) {
113
- state.tokenize = parsers.inAttribute(ch);
114
- return helpers.cont("string", "string");
97
+ state.tokenize = tokenAttribute(ch);
98
+ return cont("string", "string");
115
99
  } else if (regs.operatorChars.test(ch)) {
116
100
  stream.eatWhile(regs.operatorChars);
117
- return helpers.cont("operator", "operator");
101
+ return cont("operator", "operator");
118
102
  } else if (ch == "[" || ch == "]") {
119
- return helpers.cont("bracket", "bracket");
103
+ return cont("bracket", "bracket");
120
104
  } else if (ch == "(" || ch == ")") {
121
- return helpers.cont("bracket", "operator");
105
+ return cont("bracket", "operator");
122
106
  } else if (/\d/.test(ch)) {
123
107
  stream.eatWhile(/\d/);
124
- return helpers.cont("number", "number");
108
+ return cont("number", "number");
125
109
  } else {
126
110
 
127
111
  if (state.last == "variable") {
128
112
  if (ch == "@") {
129
113
  stream.eatWhile(regs.validIdentifier);
130
- return helpers.cont("property", "property");
114
+ return cont("property", "property");
131
115
  } else if (ch == "|") {
132
116
  stream.eatWhile(regs.validIdentifier);
133
- return helpers.cont("qualifier", "modifier");
117
+ return cont("qualifier", "modifier");
134
118
  }
135
119
  } else if (state.last == "pipe") {
136
120
  stream.eatWhile(regs.validIdentifier);
137
- return helpers.cont("qualifier", "modifier");
121
+ return cont("qualifier", "modifier");
138
122
  } else if (state.last == "whitespace") {
139
123
  stream.eatWhile(regs.validIdentifier);
140
- return helpers.cont("attribute", "modifier");
124
+ return cont("attribute", "modifier");
141
125
  } if (state.last == "property") {
142
126
  stream.eatWhile(regs.validIdentifier);
143
- return helpers.cont("property", null);
127
+ return cont("property", null);
144
128
  } else if (/\s/.test(ch)) {
145
129
  last = "whitespace";
146
130
  return null;
@@ -156,37 +140,37 @@ CodeMirror.defineMode("smarty", function(config) {
156
140
  }
157
141
  for (var i=0, j=keyFunctions.length; i<j; i++) {
158
142
  if (keyFunctions[i] == str) {
159
- return helpers.cont("keyword", "keyword");
143
+ return cont("keyword", "keyword");
160
144
  }
161
145
  }
162
146
  if (/\s/.test(ch)) {
163
147
  return null;
164
148
  }
165
- return helpers.cont("tag", "tag");
149
+ return cont("tag", "tag");
166
150
  }
167
- },
151
+ }
168
152
 
169
- inAttribute: function(quote) {
153
+ function tokenAttribute(quote) {
170
154
  return function(stream, state) {
171
155
  var prevChar = null;
172
156
  var currChar = null;
173
157
  while (!stream.eol()) {
174
158
  currChar = stream.peek();
175
159
  if (stream.next() == quote && prevChar !== '\\') {
176
- state.tokenize = parsers.smarty;
160
+ state.tokenize = tokenSmarty;
177
161
  break;
178
162
  }
179
163
  prevChar = currChar;
180
164
  }
181
165
  return "string";
182
166
  };
183
- },
167
+ }
184
168
 
185
- inBlock: function(style, terminator) {
169
+ function tokenBlock(style, terminator) {
186
170
  return function(stream, state) {
187
171
  while (!stream.eol()) {
188
172
  if (stream.match(terminator)) {
189
- state.tokenize = parsers.tokenizer;
173
+ state.tokenize = tokenTop;
190
174
  break;
191
175
  }
192
176
  stream.next();
@@ -194,28 +178,37 @@ CodeMirror.defineMode("smarty", function(config) {
194
178
  return style;
195
179
  };
196
180
  }
197
- };
198
181
 
182
+ return {
183
+ startState: function() {
184
+ return {
185
+ base: CodeMirror.startState(baseMode),
186
+ tokenize: tokenTop,
187
+ last: null,
188
+ depth: 0
189
+ };
190
+ },
191
+ copyState: function(state) {
192
+ return {
193
+ base: CodeMirror.copyState(baseMode, state.base),
194
+ tokenize: state.tokenize,
195
+ last: state.last,
196
+ depth: state.depth
197
+ };
198
+ },
199
+ innerMode: function(state) {
200
+ if (state.tokenize == tokenTop)
201
+ return {mode: baseMode, state: state.base};
202
+ },
203
+ token: function(stream, state) {
204
+ var style = state.tokenize(stream, state);
205
+ state.last = last;
206
+ return style;
207
+ },
208
+ blockCommentStart: leftDelimiter + "*",
209
+ blockCommentEnd: "*" + rightDelimiter
210
+ };
211
+ });
199
212
 
200
- // the public API for CodeMirror
201
- return {
202
- startState: function() {
203
- return {
204
- tokenize: parsers.tokenizer,
205
- mode: "smarty",
206
- last: null,
207
- depth: 0
208
- };
209
- },
210
- token: function(stream, state) {
211
- var style = state.tokenize(stream, state);
212
- state.last = last;
213
- return style;
214
- },
215
- electricChars: ""
216
- };
217
- });
218
-
219
- CodeMirror.defineMIME("text/x-smarty", "smarty");
220
-
213
+ CodeMirror.defineMIME("text/x-smarty", "smarty");
221
214
  });
@@ -1,6 +1,8 @@
1
1
  // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
2
  // Distributed under an MIT license: http://codemirror.net/LICENSE
3
3
 
4
+ // Stylus mode created by Dmitry Kiselyov http://git.io/AaRB
5
+
4
6
  (function(mod) {
5
7
  if (typeof exports == "object" && typeof module == "object") // CommonJS
6
8
  mod(require("../../lib/codemirror"));
@@ -12,433 +14,750 @@
12
14
  "use strict";
13
15
 
14
16
  CodeMirror.defineMode("stylus", function(config) {
15
-
16
- var operatorsRegexp = /^(\?:?|\+[+=]?|-[\-=]?|\*[\*=]?|\/=?|[=!:\?]?=|<=?|>=?|%=?|&&|\|=?|\~|!|\^|\\)/,
17
- delimitersRegexp = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/,
18
- wordOperatorsRegexp = wordRegexp(wordOperators),
19
- commonKeywordsRegexp = wordRegexp(commonKeywords),
20
- commonAtomsRegexp = wordRegexp(commonAtoms),
21
- commonDefRegexp = wordRegexp(commonDef),
22
- vendorPrefixesRegexp = new RegExp(/^\-(moz|ms|o|webkit)-/),
23
- cssValuesWithBracketsRegexp = new RegExp("^(" + cssValuesWithBrackets_.join("|") + ")\\([\\w\-\\#\\,\\.\\%\\s\\(\\)]*\\)");
24
-
25
- var tokenBase = function(stream, state) {
26
-
27
- if (stream.eatSpace()) return null;
28
-
29
- var ch = stream.peek();
30
-
31
- // Single line Comment
32
- if (stream.match('//')) {
17
+ var indentUnit = config.indentUnit,
18
+ tagKeywords = keySet(tagKeywords_),
19
+ tagVariablesRegexp = /^(a|b|i|s|col|em)$/i,
20
+ propertyKeywords = keySet(propertyKeywords_),
21
+ nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_),
22
+ valueKeywords = keySet(valueKeywords_),
23
+ colorKeywords = keySet(colorKeywords_),
24
+ documentTypes = keySet(documentTypes_),
25
+ documentTypesRegexp = wordRegexp(documentTypes_),
26
+ mediaFeatures = keySet(mediaFeatures_),
27
+ mediaTypes = keySet(mediaTypes_),
28
+ fontProperties = keySet(fontProperties_),
29
+ operatorsRegexp = /^\s*([.]{2,3}|&&|\|\||\*\*|[?!=:]?=|[-+*\/%<>]=?|\?:|\~)/,
30
+ wordOperatorKeywordsRegexp = wordRegexp(wordOperatorKeywords_),
31
+ blockKeywords = keySet(blockKeywords_),
32
+ vendorPrefixesRegexp = new RegExp(/^\-(moz|ms|o|webkit)-/i),
33
+ commonAtoms = keySet(commonAtoms_),
34
+ firstWordMatch = "",
35
+ states = {},
36
+ ch,
37
+ style,
38
+ type,
39
+ override;
40
+
41
+ /**
42
+ * Tokenizers
43
+ */
44
+ function tokenBase(stream, state) {
45
+ firstWordMatch = stream.string.match(/(^[\w-]+\s*=\s*$)|(^\s*[\w-]+\s*=\s*[\w-])|(^\s*(\.|#|@|\$|\&|\[|\d|\+|::?|\{|\>|~|\/)?\s*[\w-]*([a-z0-9-]|\*|\/\*)(\(|,)?)/);
46
+ state.context.line.firstWord = firstWordMatch ? firstWordMatch[0].replace(/^\s*/, "") : "";
47
+ state.context.line.indent = stream.indentation();
48
+ ch = stream.peek();
49
+
50
+ // Line comment
51
+ if (stream.match("//")) {
33
52
  stream.skipToEnd();
34
- return "comment";
53
+ return ["comment", "comment"];
35
54
  }
36
-
37
- // Multiline Comment
38
- if (stream.match('/*')) {
39
- state.tokenizer = multilineComment;
40
- return state.tokenizer(stream, state);
55
+ // Block comment
56
+ if (stream.match("/*")) {
57
+ state.tokenize = tokenCComment;
58
+ return tokenCComment(stream, state);
41
59
  }
42
-
43
- // Strings
44
- if (ch === '"' || ch === "'") {
60
+ // String
61
+ if (ch == "\"" || ch == "'") {
45
62
  stream.next();
46
- state.tokenizer = buildStringTokenizer(ch);
47
- return "string";
63
+ state.tokenize = tokenString(ch);
64
+ return state.tokenize(stream, state);
48
65
  }
49
-
50
66
  // Def
51
- if (ch === "@") {
67
+ if (ch == "@") {
52
68
  stream.next();
53
- if (stream.match(/extend/)) {
54
- dedent(state); // remove indentation after selectors
55
- } else if (stream.match(/media[\w-\s]*[\w-]/)) {
56
- indent(state);
57
- } else if(stream.eatWhile(/[\w-]/)) {
58
- if(stream.current().match(commonDefRegexp)) {
59
- indent(state);
60
- }
61
- }
62
- return "def";
63
- }
64
-
65
- // Number
66
- if (stream.match(/^-?[0-9\.]/, false)) {
67
-
68
- // Floats
69
- if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i) || stream.match(/^-?\d+\.\d*/)) {
70
-
71
- // Prevent from getting extra . on 1..
72
- if (stream.peek() == ".") {
73
- stream.backUp(1);
74
- }
75
- // Units
76
- stream.eatWhile(/[a-z%]/i);
77
- return "number";
78
- }
79
- // Integers
80
- if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/) || stream.match(/^-?0(?![\dx])/i)) {
81
- // Units
82
- stream.eatWhile(/[a-z%]/i);
83
- return "number";
84
- }
69
+ stream.eatWhile(/[\w\\-]/);
70
+ return ["def", stream.current()];
85
71
  }
86
-
87
- // Hex color and id selector
88
- if (ch === "#") {
72
+ // ID selector or Hex color
73
+ if (ch == "#") {
89
74
  stream.next();
90
-
91
75
  // Hex color
92
76
  if (stream.match(/^[0-9a-f]{6}|[0-9a-f]{3}/i)) {
93
- return "atom";
77
+ return ["atom", "atom"];
94
78
  }
95
-
96
79
  // ID selector
97
- if (stream.match(/^[\w-]+/i)) {
98
- indent(state);
99
- return "builtin";
80
+ if (stream.match(/^[a-z][\w-]*/i)) {
81
+ return ["builtin", "hash"];
100
82
  }
101
83
  }
102
-
103
84
  // Vendor prefixes
104
85
  if (stream.match(vendorPrefixesRegexp)) {
105
- return "meta";
86
+ return ["meta", "vendor-prefixes"];
106
87
  }
107
-
108
- // Gradients and animation as CSS value
109
- if (stream.match(cssValuesWithBracketsRegexp)) {
110
- return "atom";
88
+ // Numbers
89
+ if (stream.match(/^-?[0-9]?\.?[0-9]/)) {
90
+ stream.eatWhile(/[a-z%]/i);
91
+ return ["number", "unit"];
111
92
  }
112
-
113
- // Mixins / Functions with indentation
114
- if (stream.sol() && stream.match(/^\.?[a-z][\w-]*\(/i)) {
115
- stream.backUp(1);
116
- indent(state);
117
- return "keyword";
93
+ // !important|optional
94
+ if (ch == "!") {
95
+ stream.next();
96
+ return [stream.match(/^(important|optional)/i) ? "keyword": "operator", "important"];
97
+ }
98
+ // Class
99
+ if (ch == "." && stream.match(/^\.[a-z][\w-]*/i)) {
100
+ return ["qualifier", "qualifier"];
101
+ }
102
+ // url url-prefix domain regexp
103
+ if (stream.match(documentTypesRegexp)) {
104
+ if (stream.peek() == "(") state.tokenize = tokenParenthesized;
105
+ return ["property", "word"];
118
106
  }
119
-
120
107
  // Mixins / Functions
121
- if (stream.match(/^\.?[a-z][\w-]*\(/i)) {
108
+ if (stream.match(/^[a-z][\w-]*\(/i)) {
122
109
  stream.backUp(1);
123
- return "keyword";
110
+ return ["keyword", "mixin"];
124
111
  }
125
-
126
- // +Block mixins
127
- if (stream.match(/^(\+|\-)[a-z][\w-]+\(/i)) {
112
+ // Block mixins
113
+ if (stream.match(/^(\+|-)[a-z][\w-]*\(/i)) {
128
114
  stream.backUp(1);
129
- indent(state);
130
- return "keyword";
115
+ return ["keyword", "block-mixin"];
131
116
  }
132
-
133
- // url tokens
134
- if (stream.match(/^url/) && stream.peek() === "(") {
135
- state.tokenizer = urlTokens;
136
- if(!stream.peek()) {
137
- state.cursorHalf = 0;
117
+ // Parent Reference BEM naming
118
+ if (stream.string.match(/^\s*&/) && stream.match(/^[-_]+[a-z][\w-]*/)) {
119
+ return ["qualifier", "qualifier"];
120
+ }
121
+ // / Root Reference & Parent Reference
122
+ if (stream.match(/^(\/|&)(-|_|:|\.|#|[a-z])/)) {
123
+ stream.backUp(1);
124
+ return ["variable-3", "reference"];
125
+ }
126
+ if (stream.match(/^&{1}\s*$/)) {
127
+ return ["variable-3", "reference"];
128
+ }
129
+ // Variable
130
+ if (ch == "$" && stream.match(/^\$[\w-]+/i)) {
131
+ return ["variable-2", "variable-name"];
132
+ }
133
+ // Word operator
134
+ if (stream.match(wordOperatorKeywordsRegexp)) {
135
+ return ["operator", "operator"];
136
+ }
137
+ // Word
138
+ if (stream.match(/^[-_]*[a-z0-9]+[\w-]*/i)) {
139
+ if (stream.match(/^(\.|\[)[\w-\'\"\]]+/i, false)) {
140
+ if (!wordIsTag(stream.current())) {
141
+ stream.match(/[\w-]+/);
142
+ return ["variable-2", "variable-name"];
143
+ }
138
144
  }
139
- return "atom";
145
+ return ["variable-2", "word"];
140
146
  }
141
-
142
- // Class
143
- if (stream.match(/^\.[a-z][\w-]*/i)) {
144
- indent(state);
145
- return "qualifier";
147
+ // Operators
148
+ if (stream.match(operatorsRegexp)) {
149
+ return ["operator", stream.current()];
146
150
  }
147
-
148
- // & Parent Reference with BEM naming
149
- if (stream.match(/^(_|__|-|--)[a-z0-9-]+/)) {
150
- return "qualifier";
151
+ // Delimiters
152
+ if (/[:;,{}\[\]\(\)]/.test(ch)) {
153
+ stream.next();
154
+ return [null, ch];
151
155
  }
156
+ // Non-detected items
157
+ stream.next();
158
+ return [null, null];
159
+ }
152
160
 
153
- // Pseudo elements/classes
154
- if (ch == ':' && stream.match(/^::?[\w-]+/)) {
155
- indent(state);
156
- return "variable-3";
161
+ /**
162
+ * Token comment
163
+ */
164
+ function tokenCComment(stream, state) {
165
+ var maybeEnd = false, ch;
166
+ while ((ch = stream.next()) != null) {
167
+ if (maybeEnd && ch == "/") {
168
+ state.tokenize = null;
169
+ break;
170
+ }
171
+ maybeEnd = (ch == "*");
157
172
  }
173
+ return ["comment", "comment"];
174
+ }
158
175
 
159
- // Conditionals
160
- if (stream.match(wordRegexp(["for", "if", "else", "unless"]))) {
161
- indent(state);
162
- return "keyword";
163
- }
176
+ /**
177
+ * Token string
178
+ */
179
+ function tokenString(quote) {
180
+ return function(stream, state) {
181
+ var escaped = false, ch;
182
+ while ((ch = stream.next()) != null) {
183
+ if (ch == quote && !escaped) {
184
+ if (quote == ")") stream.backUp(1);
185
+ break;
186
+ }
187
+ escaped = !escaped && ch == "\\";
188
+ }
189
+ if (ch == quote || !escaped && quote != ")") state.tokenize = null;
190
+ return ["string", "string"];
191
+ };
192
+ }
164
193
 
165
- // Keywords
166
- if (stream.match(commonKeywordsRegexp)) {
167
- return "keyword";
168
- }
194
+ /**
195
+ * Token parenthesized
196
+ */
197
+ function tokenParenthesized(stream, state) {
198
+ stream.next(); // Must be "("
199
+ if (!stream.match(/\s*[\"\')]/, false))
200
+ state.tokenize = tokenString(")");
201
+ else
202
+ state.tokenize = null;
203
+ return [null, "("];
204
+ }
169
205
 
170
- // Atoms
171
- if (stream.match(commonAtomsRegexp)) {
172
- return "atom";
173
- }
206
+ /**
207
+ * Context management
208
+ */
209
+ function Context(type, indent, prev, line) {
210
+ this.type = type;
211
+ this.indent = indent;
212
+ this.prev = prev;
213
+ this.line = line || {firstWord: "", indent: 0};
214
+ }
174
215
 
175
- // Variables
176
- if (stream.match(/^\$?[a-z][\w-]+\s?=(\s|[\w-'"\$])/i)) {
177
- stream.backUp(2);
178
- var cssPropertie = stream.current().toLowerCase().match(/[\w-]+/)[0];
179
- return cssProperties[cssPropertie] === undefined ? "variable-2" : "property";
180
- } else if (stream.match(/\$[\w-\.]+/i)) {
181
- return "variable-2";
182
- } else if (stream.match(/\$?[\w-]+\.[\w-]+/i)) {
183
- var cssTypeSelector = stream.current().toLowerCase().match(/[\w]+/)[0];
184
- if(cssTypeSelectors[cssTypeSelector] === undefined) {
185
- return "variable-2";
186
- } else stream.backUp(stream.current().length);
187
- }
216
+ function pushContext(state, stream, type, indent) {
217
+ indent = indent >= 0 ? indent : indentUnit;
218
+ state.context = new Context(type, stream.indentation() + indent, state.context);
219
+ return type;
220
+ }
188
221
 
189
- // !important
190
- if (ch === "!") {
191
- stream.next();
192
- return stream.match(/^[\w]+/) ? "keyword": "operator";
193
- }
222
+ function popContext(state, currentIndent) {
223
+ var contextIndent = state.context.indent - indentUnit;
224
+ currentIndent = currentIndent || false;
225
+ state.context = state.context.prev;
226
+ if (currentIndent) state.context.indent = contextIndent;
227
+ return state.context.type;
228
+ }
194
229
 
195
- // / Root Reference
196
- if (stream.match(/^\/(:|\.|#|[a-z])/)) {
197
- stream.backUp(1);
198
- return "variable-3";
199
- }
230
+ function pass(type, stream, state) {
231
+ return states[state.context.type](type, stream, state);
232
+ }
200
233
 
201
- // Operators and delimiters
202
- if (stream.match(operatorsRegexp) || stream.match(wordOperatorsRegexp)) {
203
- return "operator";
204
- }
205
- if (stream.match(delimitersRegexp)) {
206
- return null;
207
- }
234
+ function popAndPass(type, stream, state, n) {
235
+ for (var i = n || 1; i > 0; i--)
236
+ state.context = state.context.prev;
237
+ return pass(type, stream, state);
238
+ }
208
239
 
209
- // & Parent Reference
210
- if (ch === "&") {
211
- stream.next();
212
- return "variable-3";
213
- }
240
+
241
+ /**
242
+ * Parser
243
+ */
244
+ function wordIsTag(word) {
245
+ return word.toLowerCase() in tagKeywords;
246
+ }
247
+
248
+ function wordIsProperty(word) {
249
+ word = word.toLowerCase();
250
+ return word in propertyKeywords || word in fontProperties;
251
+ }
252
+
253
+ function wordIsBlock(word) {
254
+ return word.toLowerCase() in blockKeywords;
255
+ }
256
+
257
+ function wordIsVendorPrefix(word) {
258
+ return word.toLowerCase().match(vendorPrefixesRegexp);
259
+ }
260
+
261
+ function wordAsValue(word) {
262
+ var wordLC = word.toLowerCase();
263
+ var override = "variable-2";
264
+ if (wordIsTag(word)) override = "tag";
265
+ else if (wordIsBlock(word)) override = "block-keyword";
266
+ else if (wordIsProperty(word)) override = "property";
267
+ else if (wordLC in valueKeywords || wordLC in commonAtoms) override = "atom";
268
+ else if (wordLC == "return" || wordLC in colorKeywords) override = "keyword";
214
269
 
215
270
  // Font family
216
- if (stream.match(/^[A-Z][a-z0-9-]+/)) {
217
- return "string";
218
- }
271
+ else if (word.match(/^[A-Z]/)) override = "string";
272
+ return override;
273
+ }
219
274
 
220
- // CSS rule
221
- // NOTE: Some css selectors and property values have the same name
222
- // (embed, menu, pre, progress, sub, table),
223
- // so they will have the same color (.cm-atom).
224
- if (stream.match(/[\w-]*/i)) {
275
+ function typeIsBlock(type, stream) {
276
+ return ((endOfLine(stream) && (type == "{" || type == "]" || type == "hash" || type == "qualifier")) || type == "block-mixin");
277
+ }
225
278
 
226
- var word = stream.current().toLowerCase();
279
+ function typeIsInterpolation(type, stream) {
280
+ return type == "{" && stream.match(/^\s*\$?[\w-]+/i, false);
281
+ }
227
282
 
228
- if(cssProperties[word] !== undefined) {
229
- // CSS property
230
- if(!stream.eol())
231
- return "property";
232
- else
233
- return "variable-2";
234
-
235
- } else if(cssValues[word] !== undefined) {
236
- // CSS value
237
- return "atom";
238
-
239
- } else if(cssTypeSelectors[word] !== undefined) {
240
- // CSS type selectors
241
- indent(state);
242
- return "tag";
243
-
244
- } else if(word) {
245
- // By default variable-2
246
- return "variable-2";
247
- }
248
- }
283
+ function typeIsPseudo(type, stream) {
284
+ return type == ":" && stream.match(/^[a-z-]+/, false);
285
+ }
249
286
 
250
- // Handle non-detected items
251
- stream.next();
252
- return null;
287
+ function startOfLine(stream) {
288
+ return stream.sol() || stream.string.match(new RegExp("^\\s*" + escapeRegExp(stream.current())));
289
+ }
253
290
 
254
- };
291
+ function endOfLine(stream) {
292
+ return stream.eol() || stream.match(/^\s*$/, false);
293
+ }
294
+
295
+ function firstWordOfLine(line) {
296
+ var re = /^\s*[-_]*[a-z0-9]+[\w-]*/i;
297
+ var result = typeof line == "string" ? line.match(re) : line.string.match(re);
298
+ return result ? result[0].replace(/^\s*/, "") : "";
299
+ }
255
300
 
256
- var tokenLexer = function(stream, state) {
257
301
 
258
- if (stream.sol()) {
259
- state.indentCount = 0;
302
+ /**
303
+ * Block
304
+ */
305
+ states.block = function(type, stream, state) {
306
+ if ((type == "comment" && startOfLine(stream)) ||
307
+ (type == "," && endOfLine(stream)) ||
308
+ type == "mixin") {
309
+ return pushContext(state, stream, "block", 0);
310
+ }
311
+ if (typeIsInterpolation(type, stream)) {
312
+ return pushContext(state, stream, "interpolation");
313
+ }
314
+ if (endOfLine(stream) && type == "]") {
315
+ if (!/^\s*(\.|#|:|\[|\*|&)/.test(stream.string) && !wordIsTag(firstWordOfLine(stream))) {
316
+ return pushContext(state, stream, "block", 0);
317
+ }
318
+ }
319
+ if (typeIsBlock(type, stream, state)) {
320
+ return pushContext(state, stream, "block");
321
+ }
322
+ if (type == "}" && endOfLine(stream)) {
323
+ return pushContext(state, stream, "block", 0);
324
+ }
325
+ if (type == "variable-name") {
326
+ return pushContext(state, stream, "variableName");
327
+ }
328
+ if (type == "=") {
329
+ if (!endOfLine(stream) && !wordIsBlock(firstWordOfLine(stream))) {
330
+ return pushContext(state, stream, "block", 0);
331
+ }
332
+ return pushContext(state, stream, "block");
260
333
  }
334
+ if (type == "*") {
335
+ if (endOfLine(stream) || stream.match(/\s*(,|\.|#|\[|:|{)/,false)) {
336
+ override = "tag";
337
+ return pushContext(state, stream, "block");
338
+ }
339
+ }
340
+ if (typeIsPseudo(type, stream)) {
341
+ return pushContext(state, stream, "pseudo");
342
+ }
343
+ if (/@(font-face|media|supports|(-moz-)?document)/.test(type)) {
344
+ return pushContext(state, stream, endOfLine(stream) ? "block" : "atBlock");
345
+ }
346
+ if (/@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
347
+ return pushContext(state, stream, "keyframes");
348
+ }
349
+ if (/@extends?/.test(type)) {
350
+ return pushContext(state, stream, "extend", 0);
351
+ }
352
+ if (type && type.charAt(0) == "@") {
261
353
 
262
- var style = state.tokenizer(stream, state);
263
- var current = stream.current();
354
+ // Property Lookup
355
+ if (stream.indentation() > 0 && wordIsProperty(stream.current().slice(1))) {
356
+ override = "variable-2";
357
+ return "block";
358
+ }
359
+ if (/(@import|@require|@charset)/.test(type)) {
360
+ return pushContext(state, stream, "block", 0);
361
+ }
362
+ return pushContext(state, stream, "block");
363
+ }
364
+ if (type == "reference" && endOfLine(stream)) {
365
+ return pushContext(state, stream, "block");
366
+ }
367
+ if (type == "(") {
368
+ return pushContext(state, stream, "parens");
369
+ }
264
370
 
265
- if (stream.eol() && (current === "}" || current === ",")) {
266
- dedent(state);
371
+ if (type == "vendor-prefixes") {
372
+ return pushContext(state, stream, "vendorPrefixes");
267
373
  }
374
+ if (type == "word") {
375
+ var word = stream.current();
376
+ override = wordAsValue(word);
377
+
378
+ if (override == "property") {
379
+ if (startOfLine(stream)) {
380
+ return pushContext(state, stream, "block", 0);
381
+ } else {
382
+ override = "atom";
383
+ return "block";
384
+ }
385
+ }
268
386
 
269
- if (style !== null) {
270
- var startOfToken = stream.pos - current.length;
271
- var withCurrentIndent = startOfToken + (config.indentUnit * state.indentCount);
387
+ if (override == "tag") {
272
388
 
273
- var newScopes = [];
389
+ // tag is a css value
390
+ if (/embed|menu|pre|progress|sub|table/.test(word)) {
391
+ if (wordIsProperty(firstWordOfLine(stream))) {
392
+ override = "atom";
393
+ return "block";
394
+ }
395
+ }
274
396
 
275
- for (var i = 0; i < state.scopes.length; i++) {
276
- var scope = state.scopes[i];
397
+ // tag is an attribute
398
+ if (stream.string.match(new RegExp("\\[\\s*" + word + "|" + word +"\\s*\\]"))) {
399
+ override = "atom";
400
+ return "block";
401
+ }
277
402
 
278
- if (scope.offset <= withCurrentIndent) {
279
- newScopes.push(scope);
403
+ // tag is a variable
404
+ if (tagVariablesRegexp.test(word)) {
405
+ if ((startOfLine(stream) && stream.string.match(/=/)) ||
406
+ (!startOfLine(stream) &&
407
+ !stream.string.match(/^(\s*\.|#|\&|\[|\/|>|\*)/) &&
408
+ !wordIsTag(firstWordOfLine(stream)))) {
409
+ override = "variable-2";
410
+ if (wordIsBlock(firstWordOfLine(stream))) return "block";
411
+ return pushContext(state, stream, "block", 0);
412
+ }
280
413
  }
414
+
415
+ if (endOfLine(stream)) return pushContext(state, stream, "block");
281
416
  }
417
+ if (override == "block-keyword") {
418
+ override = "keyword";
282
419
 
283
- state.scopes = newScopes;
420
+ // Postfix conditionals
421
+ if (stream.current(/(if|unless)/) && !startOfLine(stream)) {
422
+ return "block";
423
+ }
424
+ return pushContext(state, stream, "block");
425
+ }
426
+ if (word == "return") return pushContext(state, stream, "block", 0);
284
427
  }
285
-
286
- return style;
428
+ return state.context.type;
287
429
  };
288
430
 
289
- return {
290
- startState: function() {
291
- return {
292
- tokenizer: tokenBase,
293
- scopes: [{offset: 0, type: 'styl'}]
294
- };
295
- },
296
431
 
297
- token: function(stream, state) {
298
- var style = tokenLexer(stream, state);
299
- state.lastToken = { style: style, content: stream.current() };
300
- return style;
301
- },
432
+ /**
433
+ * Parens
434
+ */
435
+ states.parens = function(type, stream, state) {
436
+ if (type == "(") return pushContext(state, stream, "parens");
437
+ if (type == ")") {
438
+ if (state.context.prev.type == "parens") {
439
+ return popContext(state);
440
+ }
441
+ if ((stream.string.match(/^[a-z][\w-]*\(/i) && endOfLine(stream)) ||
442
+ wordIsBlock(firstWordOfLine(stream)) ||
443
+ /(\.|#|:|\[|\*|&|>|~|\+|\/)/.test(firstWordOfLine(stream)) ||
444
+ (!stream.string.match(/^-?[a-z][\w-\.\[\]\'\"]*\s*=/) &&
445
+ wordIsTag(firstWordOfLine(stream)))) {
446
+ return pushContext(state, stream, "block");
447
+ }
448
+ if (stream.string.match(/^-?[a-z][\w-\.\[\]\'\"]*\s*=/) ||
449
+ stream.string.match(/^\s*(\(|\)|[0-9])/) ||
450
+ stream.string.match(/^\s+[a-z][\w-]*\(/i) ||
451
+ stream.string.match(/^\s+-?[a-z]/i)) {
452
+ return pushContext(state, stream, "block", 0);
453
+ }
454
+ if (endOfLine(stream)) return pushContext(state, stream, "block");
455
+ else return pushContext(state, stream, "block", 0);
456
+ }
457
+ if (type && type.charAt(0) == "@" && wordIsProperty(stream.current().slice(1))) {
458
+ override = "variable-2";
459
+ }
460
+ if (type == "word") {
461
+ var word = stream.current();
462
+ override = wordAsValue(word);
463
+ if (override == "tag" && tagVariablesRegexp.test(word)) {
464
+ override = "variable-2";
465
+ }
466
+ if (override == "property" || word == "to") override = "atom";
467
+ }
468
+ if (type == "variable-name") {
469
+ return pushContext(state, stream, "variableName");
470
+ }
471
+ if (typeIsPseudo(type, stream)) {
472
+ return pushContext(state, stream, "pseudo");
473
+ }
474
+ return state.context.type;
475
+ };
302
476
 
303
- indent: function(state) {
304
- return state.scopes[0].offset;
305
- },
306
-
307
- lineComment: "//",
308
- fold: "indent"
309
477
 
478
+ /**
479
+ * Vendor prefixes
480
+ */
481
+ states.vendorPrefixes = function(type, stream, state) {
482
+ if (type == "word") {
483
+ override = "property";
484
+ return pushContext(state, stream, "block", 0);
485
+ }
486
+ return popContext(state);
310
487
  };
311
488
 
312
- function urlTokens(stream, state) {
313
- var ch = stream.peek();
314
489
 
315
- if (ch === ")") {
316
- stream.next();
317
- state.tokenizer = tokenBase;
318
- return "operator";
319
- } else if (ch === "(") {
320
- stream.next();
321
- stream.eatSpace();
490
+ /**
491
+ * Pseudo
492
+ */
493
+ states.pseudo = function(type, stream, state) {
494
+ if (!wordIsProperty(firstWordOfLine(stream.string))) {
495
+ stream.match(/^[a-z-]+/);
496
+ override = "variable-3";
497
+ if (endOfLine(stream)) return pushContext(state, stream, "block");
498
+ return popContext(state);
499
+ }
500
+ return popAndPass(type, stream, state);
501
+ };
322
502
 
323
- return "operator";
324
- } else if (ch === "'" || ch === '"') {
325
- state.tokenizer = buildStringTokenizer(stream.next());
326
- return "string";
327
- } else {
328
- state.tokenizer = buildStringTokenizer(")", false);
329
- return "string";
503
+
504
+ /**
505
+ * atBlock
506
+ */
507
+ states.atBlock = function(type, stream, state) {
508
+ if (type == "(") return pushContext(state, stream, "atBlock_parens");
509
+ if (typeIsBlock(type, stream, state)) {
510
+ return pushContext(state, stream, "block");
330
511
  }
331
- }
512
+ if (typeIsInterpolation(type, stream)) {
513
+ return pushContext(state, stream, "interpolation");
514
+ }
515
+ if (type == "word") {
516
+ var word = stream.current().toLowerCase();
517
+ if (/^(only|not|and|or)$/.test(word))
518
+ override = "keyword";
519
+ else if (documentTypes.hasOwnProperty(word))
520
+ override = "tag";
521
+ else if (mediaTypes.hasOwnProperty(word))
522
+ override = "attribute";
523
+ else if (mediaFeatures.hasOwnProperty(word))
524
+ override = "property";
525
+ else if (nonStandardPropertyKeywords.hasOwnProperty(word))
526
+ override = "string-2";
527
+ else override = wordAsValue(stream.current());
528
+ if (override == "tag" && endOfLine(stream)) {
529
+ return pushContext(state, stream, "block");
530
+ }
531
+ }
532
+ if (type == "operator" && /^(not|and|or)$/.test(stream.current())) {
533
+ override = "keyword";
534
+ }
535
+ return state.context.type;
536
+ };
332
537
 
333
- function multilineComment(stream, state) {
334
- if (stream.skipTo("*/")) {
335
- stream.next();
336
- stream.next();
337
- state.tokenizer = tokenBase;
338
- } else {
339
- stream.next();
538
+ states.atBlock_parens = function(type, stream, state) {
539
+ if (type == "{" || type == "}") return state.context.type;
540
+ if (type == ")") {
541
+ if (endOfLine(stream)) return pushContext(state, stream, "block");
542
+ else return pushContext(state, stream, "atBlock");
340
543
  }
341
- return "comment";
342
- }
544
+ if (type == "word") {
545
+ var word = stream.current().toLowerCase();
546
+ override = wordAsValue(word);
547
+ if (/^(max|min)/.test(word)) override = "property";
548
+ if (override == "tag") {
549
+ tagVariablesRegexp.test(word) ? override = "variable-2" : override = "atom";
550
+ }
551
+ return state.context.type;
552
+ }
553
+ return states.atBlock(type, stream, state);
554
+ };
343
555
 
344
- function buildStringTokenizer(quote, greedy) {
345
556
 
346
- if(greedy == null) {
347
- greedy = true;
557
+ /**
558
+ * Keyframes
559
+ */
560
+ states.keyframes = function(type, stream, state) {
561
+ if (stream.indentation() == "0" && ((type == "}" && startOfLine(stream)) || type == "]" || type == "hash"
562
+ || type == "qualifier" || wordIsTag(stream.current()))) {
563
+ return popAndPass(type, stream, state);
348
564
  }
565
+ if (type == "{") return pushContext(state, stream, "keyframes");
566
+ if (type == "}") {
567
+ if (startOfLine(stream)) return popContext(state, true);
568
+ else return pushContext(state, stream, "keyframes");
569
+ }
570
+ if (type == "unit" && /^[0-9]+\%$/.test(stream.current())) {
571
+ return pushContext(state, stream, "keyframes");
572
+ }
573
+ if (type == "word") {
574
+ override = wordAsValue(stream.current());
575
+ if (override == "block-keyword") {
576
+ override = "keyword";
577
+ return pushContext(state, stream, "keyframes");
578
+ }
579
+ }
580
+ if (/@(font-face|media|supports|(-moz-)?document)/.test(type)) {
581
+ return pushContext(state, stream, endOfLine(stream) ? "block" : "atBlock");
582
+ }
583
+ if (type == "mixin") {
584
+ return pushContext(state, stream, "block", 0);
585
+ }
586
+ return state.context.type;
587
+ };
349
588
 
350
- function stringTokenizer(stream, state) {
351
- var nextChar = stream.next();
352
- var peekChar = stream.peek();
353
- var previousChar = stream.string.charAt(stream.pos-2);
354
-
355
- var endingString = ((nextChar !== "\\" && peekChar === quote) ||
356
- (nextChar === quote && previousChar !== "\\"));
357
589
 
358
- if (endingString) {
359
- if (nextChar !== quote && greedy) {
360
- stream.next();
361
- }
362
- state.tokenizer = tokenBase;
363
- return "string";
364
- } else if (nextChar === "#" && peekChar === "{") {
365
- state.tokenizer = buildInterpolationTokenizer(stringTokenizer);
366
- stream.next();
367
- return "operator";
368
- } else {
369
- return "string";
590
+ /**
591
+ * Interpolation
592
+ */
593
+ states.interpolation = function(type, stream, state) {
594
+ if (type == "{") popContext(state) && pushContext(state, stream, "block");
595
+ if (type == "}") {
596
+ if (stream.string.match(/^\s*(\.|#|:|\[|\*|&|>|~|\+|\/)/i) ||
597
+ (stream.string.match(/^\s*[a-z]/i) && wordIsTag(firstWordOfLine(stream)))) {
598
+ return pushContext(state, stream, "block");
370
599
  }
600
+ if (!stream.string.match(/^(\{|\s*\&)/) ||
601
+ stream.match(/\s*[\w-]/,false)) {
602
+ return pushContext(state, stream, "block", 0);
603
+ }
604
+ return pushContext(state, stream, "block");
605
+ }
606
+ if (type == "variable-name") {
607
+ return pushContext(state, stream, "variableName", 0);
608
+ }
609
+ if (type == "word") {
610
+ override = wordAsValue(stream.current());
611
+ if (override == "tag") override = "atom";
371
612
  }
613
+ return state.context.type;
614
+ };
372
615
 
373
- return stringTokenizer;
374
- }
375
616
 
376
- function buildInterpolationTokenizer(currentTokenizer) {
377
- return function(stream, state) {
378
- if (stream.peek() === "}") {
379
- stream.next();
380
- state.tokenizer = currentTokenizer;
381
- return "operator";
382
- } else {
383
- return tokenBase(stream, state);
384
- }
385
- };
386
- }
617
+ /**
618
+ * Extend/s
619
+ */
620
+ states.extend = function(type, stream, state) {
621
+ if (type == "[" || type == "=") return "extend";
622
+ if (type == "]") return popContext(state);
623
+ if (type == "word") {
624
+ override = wordAsValue(stream.current());
625
+ return "extend";
626
+ }
627
+ return popContext(state);
628
+ };
629
+
387
630
 
388
- function indent(state) {
389
- if (state.indentCount == 0) {
390
- state.indentCount++;
391
- var lastScopeOffset = state.scopes[0].offset;
392
- var currentOffset = lastScopeOffset + config.indentUnit;
393
- state.scopes.unshift({ offset:currentOffset });
631
+ /**
632
+ * Variable name
633
+ */
634
+ states.variableName = function(type, stream, state) {
635
+ if (type == "string" || type == "[" || type == "]" || stream.current().match(/^(\.|\$)/)) {
636
+ if (stream.current().match(/^\.[\w-]+/i)) override = "variable-2";
637
+ if (endOfLine(stream)) return popContext(state);
638
+ return "variableName";
394
639
  }
395
- }
640
+ return popAndPass(type, stream, state);
641
+ };
396
642
 
397
- function dedent(state) {
398
- if (state.scopes.length == 1) { return true; }
399
- state.scopes.shift();
400
- }
401
643
 
644
+ return {
645
+ startState: function(base) {
646
+ return {
647
+ tokenize: null,
648
+ state: "block",
649
+ context: new Context("block", base || 0, null)
650
+ };
651
+ },
652
+ token: function(stream, state) {
653
+ if (!state.tokenize && stream.eatSpace()) return null;
654
+ style = (state.tokenize || tokenBase)(stream, state);
655
+ if (style && typeof style == "object") {
656
+ type = style[1];
657
+ style = style[0];
658
+ }
659
+ override = style;
660
+ state.state = states[state.state](type, stream, state);
661
+ return override;
662
+ },
663
+ indent: function(state, textAfter, line) {
664
+
665
+ var cx = state.context,
666
+ ch = textAfter && textAfter.charAt(0),
667
+ indent = cx.indent,
668
+ lineFirstWord = firstWordOfLine(textAfter),
669
+ lineIndent = line.length - line.replace(/^\s*/, "").length,
670
+ prevLineFirstWord = state.context.prev ? state.context.prev.line.firstWord : "",
671
+ prevLineIndent = state.context.prev ? state.context.prev.line.indent : lineIndent;
672
+
673
+ if (cx.prev &&
674
+ (ch == "}" && (cx.type == "block" || cx.type == "atBlock" || cx.type == "keyframes") ||
675
+ ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
676
+ ch == "{" && (cx.type == "at"))) {
677
+ indent = cx.indent - indentUnit;
678
+ cx = cx.prev;
679
+ } else if (!(/(\})/.test(ch))) {
680
+ if (/@|\$|\d/.test(ch) ||
681
+ /^\{/.test(textAfter) ||
682
+ /^\s*\/(\/|\*)/.test(textAfter) ||
683
+ /^\s*\/\*/.test(prevLineFirstWord) ||
684
+ /^\s*[\w-\.\[\]\'\"]+\s*(\?|:|\+)?=/i.test(textAfter) ||
685
+ /^(\+|-)?[a-z][\w-]*\(/i.test(textAfter) ||
686
+ /^return/.test(textAfter) ||
687
+ wordIsBlock(lineFirstWord)) {
688
+ indent = lineIndent;
689
+ } else if (/(\.|#|:|\[|\*|&|>|~|\+|\/)/.test(ch) || wordIsTag(lineFirstWord)) {
690
+ if (/\,\s*$/.test(prevLineFirstWord)) {
691
+ indent = prevLineIndent;
692
+ } else if (/^\s+/.test(line) && (/(\.|#|:|\[|\*|&|>|~|\+|\/)/.test(prevLineFirstWord) || wordIsTag(prevLineFirstWord))) {
693
+ indent = lineIndent <= prevLineIndent ? prevLineIndent : prevLineIndent + indentUnit;
694
+ } else {
695
+ indent = lineIndent;
696
+ }
697
+ } else if (!/,\s*$/.test(line) && (wordIsVendorPrefix(lineFirstWord) || wordIsProperty(lineFirstWord))) {
698
+ if (wordIsBlock(prevLineFirstWord)) {
699
+ indent = lineIndent <= prevLineIndent ? prevLineIndent : prevLineIndent + indentUnit;
700
+ } else if (/^\{/.test(prevLineFirstWord)) {
701
+ indent = lineIndent <= prevLineIndent ? lineIndent : prevLineIndent + indentUnit;
702
+ } else if (wordIsVendorPrefix(prevLineFirstWord) || wordIsProperty(prevLineFirstWord)) {
703
+ indent = lineIndent >= prevLineIndent ? prevLineIndent : lineIndent;
704
+ } else if (/^(\.|#|:|\[|\*|&|@|\+|\-|>|~|\/)/.test(prevLineFirstWord) ||
705
+ /=\s*$/.test(prevLineFirstWord) ||
706
+ wordIsTag(prevLineFirstWord) ||
707
+ /^\$[\w-\.\[\]\'\"]/.test(prevLineFirstWord)) {
708
+ indent = prevLineIndent + indentUnit;
709
+ } else {
710
+ indent = lineIndent;
711
+ }
712
+ }
713
+ }
714
+ return indent;
715
+ },
716
+ electricChars: "}",
717
+ lineComment: "//",
718
+ fold: "indent"
719
+ };
402
720
  });
403
721
 
404
- // https://developer.mozilla.org/en-US/docs/Web/HTML/Element
405
- var cssTypeSelectors_ = ["a","abbr","address","area","article","aside","audio", "b", "base","bdi","bdo","bgsound","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","div","dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","kbd","keygen","label","legend","li","link","main","map","mark","marquee","menu","menuitem","meta","meter","nav","nobr","noframes","noscript","object","ol","optgroup","option","output","p","param","pre","progress","q","rp","rt","ruby","s","samp","script","section","select","small","source","span","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","title","tr","track","u","ul","var","video","wbr"];
406
- // https://github.com/csscomb/csscomb.js/blob/master/config/zen.json
407
- var cssProperties_ = ["position","top","right","bottom","left","z-index","display","visibility","flex-direction","flex-order","flex-pack","float","clear","flex-align","overflow","overflow-x","overflow-y","overflow-scrolling","clip","box-sizing","margin","margin-top","margin-right","margin-bottom","margin-left","padding","padding-top","padding-right","padding-bottom","padding-left","min-width","min-height","max-width","max-height","width","height","outline","outline-width","outline-style","outline-color","outline-offset","border","border-spacing","border-collapse","border-width","border-style","border-color","border-top","border-top-width","border-top-style","border-top-color","border-right","border-right-width","border-right-style","border-right-color","border-bottom","border-bottom-width","border-bottom-style","border-bottom-color","border-left","border-left-width","border-left-style","border-left-color","border-radius","border-top-left-radius","border-top-right-radius","border-bottom-right-radius","border-bottom-left-radius","border-image","border-image-source","border-image-slice","border-image-width","border-image-outset","border-image-repeat","border-top-image","border-right-image","border-bottom-image","border-left-image","border-corner-image","border-top-left-image","border-top-right-image","border-bottom-right-image","border-bottom-left-image","background","filter:progid:DXImageTransform\\.Microsoft\\.AlphaImageLoader","background-color","background-image","background-attachment","background-position","background-position-x","background-position-y","background-clip","background-origin","background-size","background-repeat","box-decoration-break","box-shadow","color","table-layout","caption-side","empty-cells","list-style","list-style-position","list-style-type","list-style-image","quotes","content","counter-increment","counter-reset","writing-mode","vertical-align","text-align","text-align-last","text-decoration","text-emphasis","text-emphasis-position","text-emphasis-style","text-emphasis-color","text-indent","-ms-text-justify","text-justify","text-outline","text-transform","text-wrap","text-overflow","text-overflow-ellipsis","text-overflow-mode","text-size-adjust","text-shadow","white-space","word-spacing","word-wrap","word-break","tab-size","hyphens","letter-spacing","font","font-weight","font-style","font-variant","font-size-adjust","font-stretch","font-size","font-family","src","line-height","opacity","filter:\\\\\\\\'progid:DXImageTransform.Microsoft.Alpha","filter:progid:DXImageTransform.Microsoft.Alpha\\(Opacity","interpolation-mode","filter","resize","cursor","nav-index","nav-up","nav-right","nav-down","nav-left","transition","transition-delay","transition-timing-function","transition-duration","transition-property","transform","transform-origin","animation","animation-name","animation-duration","animation-play-state","animation-timing-function","animation-delay","animation-iteration-count","animation-direction","pointer-events","unicode-bidi","direction","columns","column-span","column-width","column-count","column-fill","column-gap","column-rule","column-rule-width","column-rule-style","column-rule-color","break-before","break-inside","break-after","page-break-before","page-break-inside","page-break-after","orphans","widows","zoom","max-zoom","min-zoom","user-zoom","orientation","text-rendering","speak","animation-fill-mode","backface-visibility","user-drag","user-select","appearance"];
408
- // https://github.com/codemirror/CodeMirror/blob/master/mode/css/css.js#L501
409
- var cssValues_ = ["above","absolute","activeborder","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","auto","avoid","avoid-column","avoid-page","avoid-region","background","backwards","baseline","below","bidi-override","binary","bengali","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","button-bevel","buttonface","buttonhighlight","buttonshadow","buttontext","cambodian","capitalize","caps-lock-indicator","captiontext","caret","cell","center","checkbox","circle","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","column","compact","condensed","contain","content","content-box","context-menu","continuous","copy","cover","crop","cross","crosshair","currentcolor","cursive","dashed","decimal","decimal-leading-zero","default","default-button","destination-atop","destination-in","destination-out","destination-over","devanagari","disc","discard","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ew-resize","expanded","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","footnotes","forwards","from","geometricPrecision","georgian","graytext","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hebrew","help","hidden","hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-table","inset","inside","intrinsic","invert","italic","justify","kannada","katakana","katakana-iroha","keep-all","khmer","landscape","lao","large","larger","left","level","lighter","line-through","linear","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","malayalam","match","media-controls-background","media-current-time-display","media-fullscreen-button","media-mute-button","media-play-button","media-return-to-realtime-button","media-rewind-button","media-seek-back-button","media-seek-forward-button","media-slider","media-sliderthumb","media-time-remaining-display","media-volume-slider","media-volume-slider-container","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menulist-text","menulist-textfield","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","nw-resize","nwse-resize","oblique","octal","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","round","row-resize","rtl","run-in","running","s-resize","sans-serif","scroll","scrollbar","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","semi-condensed","semi-expanded","separate","serif","show","sidama","single","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small-caps","small-caption","smaller","solid","somali","source-atop","source-in","source-out","source-over","space","square","square-button","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","telugu","text","text-bottom","text-top","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","transparent","ultra-condensed","ultra-expanded","underline","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","x-large","x-small","xor","xx-large","xx-small","bicubic","optimizespeed","grayscale"];
410
- var cssColorValues_ = ["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"];
411
- var cssValuesWithBrackets_ = ["gradient","linear-gradient","radial-gradient","repeating-linear-gradient","repeating-radial-gradient","cubic-bezier","translateX","translateY","translate3d","rotate3d","scale","scale3d","perspective","skewX"];
412
-
413
- var wordOperators = ["in", "and", "or", "not", "is a", "is", "isnt", "defined", "if unless"],
414
- commonKeywords = ["for", "if", "else", "unless", "return"],
415
- commonAtoms = ["null", "true", "false", "href", "title", "type", "not-allowed", "readonly", "disabled"],
416
- commonDef = ["@font-face", "@keyframes", "@media", "@viewport", "@page", "@host", "@supports", "@block", "@css"],
417
- cssTypeSelectors = keySet(cssTypeSelectors_),
418
- cssProperties = keySet(cssProperties_),
419
- cssValues = keySet(cssValues_.concat(cssColorValues_)),
420
- hintWords = wordOperators.concat(commonKeywords,
421
- commonAtoms,
422
- commonDef,
423
- cssTypeSelectors_,
424
- cssProperties_,
425
- cssValues_,
426
- cssValuesWithBrackets_,
427
- cssColorValues_);
722
+ // developer.mozilla.org/en-US/docs/Web/HTML/Element
723
+ var tagKeywords_ = ["a","abbr","address","area","article","aside","audio", "b", "base","bdi", "bdo","bgsound","blockquote","body","br","button","canvas","caption","cite", "code","col","colgroup","data","datalist","dd","del","details","dfn","div", "dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1", "h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe", "img","input","ins","kbd","keygen","label","legend","li","link","main","map", "mark","marquee","menu","menuitem","meta","meter","nav","nobr","noframes", "noscript","object","ol","optgroup","option","output","p","param","pre", "progress","q","rp","rt","ruby","s","samp","script","section","select", "small","source","span","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","track", "u","ul","var","video"];
724
+
725
+ // github.com/codemirror/CodeMirror/blob/master/mode/css/css.js
726
+ var documentTypes_ = ["domain", "regexp", "url", "url-prefix"];
727
+ var mediaTypes_ = ["all","aural","braille","handheld","print","projection","screen","tty","tv","embossed"];
728
+ var mediaFeatures_ = ["width","min-width","max-width","height","min-height","max-height","device-width","min-device-width","max-device-width","device-height","min-device-height","max-device-height","aspect-ratio","min-aspect-ratio","max-aspect-ratio","device-aspect-ratio","min-device-aspect-ratio","max-device-aspect-ratio","color","min-color","max-color","color-index","min-color-index","max-color-index","monochrome","min-monochrome","max-monochrome","resolution","min-resolution","max-resolution","scan","grid"];
729
+ var propertyKeywords_ = ["align-content","align-items","align-self","alignment-adjust","alignment-baseline","anchor-point","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","azimuth","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","baseline-shift","binding","bleed","bookmark-label","bookmark-level","bookmark-state","bookmark-target","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","color","color-profile","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","crop","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","drop-initial-after-adjust","drop-initial-after-align","drop-initial-before-adjust","drop-initial-before-align","drop-initial-size","drop-initial-value","elevation","empty-cells","fit","fit-position","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","float-offset","flow-from","flow-into","font","font-feature-settings","font-family","font-kerning","font-language-override","font-size","font-size-adjust","font-stretch","font-style","font-synthesis","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-weight","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-position","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","inline-box-align","justify-content","left","letter-spacing","line-break","line-height","line-stacking","line-stacking-ruby","line-stacking-shift","line-stacking-strategy","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marker-offset","marks","marquee-direction","marquee-loop","marquee-play-count","marquee-speed","marquee-style","max-height","max-width","min-height","min-width","move-to","nav-down","nav-index","nav-left","nav-right","nav-up","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-style","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","page-policy","pause","pause-after","pause-before","perspective","perspective-origin","pitch","pitch-range","play-during","position","presentation-level","punctuation-trim","quotes","region-break-after","region-break-before","region-break-inside","region-fragment","rendering-intent","resize","rest","rest-after","rest-before","richness","right","rotation","rotation-point","ruby-align","ruby-overhang","ruby-position","ruby-span","shape-image-threshold","shape-inside","shape-margin","shape-outside","size","speak","speak-as","speak-header","speak-numeral","speak-punctuation","speech-rate","stress","string-set","tab-size","table-layout","target","target-name","target-new","target-position","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-height","text-indent","text-justify","text-outline","text-overflow","text-shadow","text-size-adjust","text-space-collapse","text-transform","text-underline-position","text-wrap","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","volume","white-space","widows","width","word-break","word-spacing","word-wrap","z-index","clip-path","clip-rule","mask","enable-background","filter","flood-color","flood-opacity","lighting-color","stop-color","stop-opacity","pointer-events","color-interpolation","color-interpolation-filters","color-rendering","fill","fill-opacity","fill-rule","image-rendering","marker","marker-end","marker-mid","marker-start","shape-rendering","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-rendering","baseline-shift","dominant-baseline","glyph-orientation-horizontal","glyph-orientation-vertical","text-anchor","writing-mode","font-smoothing","osx-font-smoothing"];
730
+ var nonStandardPropertyKeywords_ = ["scrollbar-arrow-color","scrollbar-base-color","scrollbar-dark-shadow-color","scrollbar-face-color","scrollbar-highlight-color","scrollbar-shadow-color","scrollbar-3d-light-color","scrollbar-track-color","shape-inside","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","zoom"];
731
+ var fontProperties_ = ["font-family","src","unicode-range","font-variant","font-feature-settings","font-stretch","font-weight","font-style"];
732
+ var colorKeywords_ = ["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"];
733
+ var valueKeywords_ = ["above","absolute","activeborder","additive","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alphabetic","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","attr","auto","avoid","avoid-column","avoid-page","avoid-region","background","backwards","baseline","below","bidi-override","binary","bengali","blink","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","bullets","button","button-bevel","buttonface","buttonhighlight","buttonshadow","buttontext","calc","cambodian","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-decimal","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","column","compact","condensed","contain","content","content-box","context-menu","continuous","copy","counter","counters","cover","crop","cross","crosshair","currentcolor","cursive","cyclic","dashed","decimal","decimal-leading-zero","default","default-button","destination-atop","destination-in","destination-out","destination-over","devanagari","disc","discard","disclosure-closed","disclosure-open","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ethiopic-numeric","ew-resize","expanded","extends","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","flex","footnotes","forwards","from","geometricPrecision","georgian","graytext","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hebrew","help","hidden","hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-flex","inline-table","inset","inside","intrinsic","invert","italic","japanese-formal","japanese-informal","justify","kannada","katakana","katakana-iroha","keep-all","khmer","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","landscape","lao","large","larger","left","level","lighter","line-through","linear","linear-gradient","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","malayalam","match","matrix","matrix3d","media-controls-background","media-current-time-display","media-fullscreen-button","media-mute-button","media-play-button","media-return-to-realtime-button","media-rewind-button","media-seek-back-button","media-seek-forward-button","media-slider","media-sliderthumb","media-time-remaining-display","media-volume-slider","media-volume-slider-container","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menulist-text","menulist-textfield","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","numbers","numeric","nw-resize","nwse-resize","oblique","octal","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","perspective","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radial-gradient","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeating-linear-gradient","repeating-radial-gradient","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","rotate","rotate3d","rotateX","rotateY","rotateZ","round","row-resize","rtl","run-in","running","s-resize","sans-serif","scale","scale3d","scaleX","scaleY","scaleZ","scroll","scrollbar","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","semi-condensed","semi-expanded","separate","serif","show","sidama","simp-chinese-formal","simp-chinese-informal","single","skew","skewX","skewY","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","solid","somali","source-atop","source-in","source-out","source-over","space","spell-out","square","square-button","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","symbolic","symbols","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","tamil","telugu","text","text-bottom","text-top","textarea","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","trad-chinese-formal","trad-chinese-informal","translate","translate3d","translateX","translateY","translateZ","transparent","ultra-condensed","ultra-expanded","underline","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","var","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","words","x-large","x-small","xor","xx-large","xx-small","bicubic","optimizespeed","grayscale"];
734
+
735
+ var wordOperatorKeywords_ = ["in","and","or","not","is not","is a","is","isnt","defined","if unless"],
736
+ blockKeywords_ = ["for","if","else","unless", "from", "to"],
737
+ commonAtoms_ = ["null","true","false","href","title","type","not-allowed","readonly","disabled"],
738
+ commonDef_ = ["@font-face", "@keyframes", "@media", "@viewport", "@page", "@host", "@supports", "@block", "@css"];
739
+
740
+ var hintWords = tagKeywords_.concat(documentTypes_,mediaTypes_,mediaFeatures_,
741
+ propertyKeywords_,nonStandardPropertyKeywords_,
742
+ colorKeywords_,valueKeywords_,fontProperties_,
743
+ wordOperatorKeywords_,blockKeywords_,
744
+ commonAtoms_,commonDef_);
428
745
 
429
746
  function wordRegexp(words) {
747
+ words = words.sort(function(a,b){return b > a;});
430
748
  return new RegExp("^((" + words.join(")|(") + "))\\b");
431
- };
749
+ }
432
750
 
433
751
  function keySet(array) {
434
752
  var keys = {};
435
- for (var i = 0; i < array.length; ++i) {
436
- keys[array[i]] = true;
437
- }
753
+ for (var i = 0; i < array.length; ++i) keys[array[i]] = true;
438
754
  return keys;
439
- };
755
+ }
756
+
757
+ function escapeRegExp(text) {
758
+ return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
759
+ }
440
760
 
441
761
  CodeMirror.registerHelper("hintWords", "stylus", hintWords);
442
762
  CodeMirror.defineMIME("text/x-styl", "stylus");
443
-
444
763
  });