codemirror-rails 3.20 → 3.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +240 -135
  4. data/vendor/assets/javascripts/codemirror/addons/comment/comment.js +6 -2
  5. data/vendor/assets/javascripts/codemirror/addons/comment/continuecomment.js +1 -1
  6. data/vendor/assets/javascripts/codemirror/addons/dialog/dialog.js +1 -0
  7. data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +5 -3
  8. data/vendor/assets/javascripts/codemirror/addons/edit/closetag.js +10 -6
  9. data/vendor/assets/javascripts/codemirror/addons/edit/continuelist.js +2 -0
  10. data/vendor/assets/javascripts/codemirror/addons/edit/matchbrackets.js +1 -1
  11. data/vendor/assets/javascripts/codemirror/addons/fold/comment-fold.js +3 -1
  12. data/vendor/assets/javascripts/codemirror/addons/fold/foldcode.js +13 -2
  13. data/vendor/assets/javascripts/codemirror/addons/fold/foldgutter.js +1 -1
  14. data/vendor/assets/javascripts/codemirror/addons/fold/indent-fold.js +2 -2
  15. data/vendor/assets/javascripts/codemirror/addons/fold/xml-fold.js +6 -0
  16. data/vendor/assets/javascripts/codemirror/addons/hint/anyword-hint.js +3 -5
  17. data/vendor/assets/javascripts/codemirror/addons/hint/css-hint.js +29 -33
  18. data/vendor/assets/javascripts/codemirror/addons/hint/javascript-hint.js +1 -1
  19. data/vendor/assets/javascripts/codemirror/addons/hint/pig-hint.js +1 -1
  20. data/vendor/assets/javascripts/codemirror/addons/hint/python-hint.js +1 -5
  21. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +58 -9
  22. data/vendor/assets/javascripts/codemirror/addons/hint/sql-hint.js +58 -17
  23. data/vendor/assets/javascripts/codemirror/addons/hint/xml-hint.js +5 -5
  24. data/vendor/assets/javascripts/codemirror/addons/lint/lint.js +1 -1
  25. data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +6 -1
  26. data/vendor/assets/javascripts/codemirror/addons/mode/multiplex.js +5 -3
  27. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode-standalone.js +26 -11
  28. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.js +1 -1
  29. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.node.js +22 -11
  30. data/vendor/assets/javascripts/codemirror/addons/search/search.js +22 -9
  31. data/vendor/assets/javascripts/codemirror/addons/search/searchcursor.js +48 -24
  32. data/vendor/assets/javascripts/codemirror/addons/selection/active-line.js +15 -9
  33. data/vendor/assets/javascripts/codemirror/addons/tern/tern.js +3 -3
  34. data/vendor/assets/javascripts/codemirror/addons/wrap/hardwrap.js +21 -9
  35. data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +12 -1
  36. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +110 -28
  37. data/vendor/assets/javascripts/codemirror/modes/clike.js +28 -9
  38. data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +3 -4
  39. data/vendor/assets/javascripts/codemirror/modes/css.js +341 -297
  40. data/vendor/assets/javascripts/codemirror/modes/erlang.js +302 -179
  41. data/vendor/assets/javascripts/codemirror/modes/gfm.js +10 -5
  42. data/vendor/assets/javascripts/codemirror/modes/gherkin.js +45 -50
  43. data/vendor/assets/javascripts/codemirror/modes/haml.js +0 -4
  44. data/vendor/assets/javascripts/codemirror/modes/haskell.js +5 -3
  45. data/vendor/assets/javascripts/codemirror/modes/htmlembedded.js +0 -2
  46. data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +0 -2
  47. data/vendor/assets/javascripts/codemirror/modes/javascript.js +43 -30
  48. data/vendor/assets/javascripts/codemirror/modes/jinja2.js +13 -3
  49. data/vendor/assets/javascripts/codemirror/modes/less.js +7 -6
  50. data/vendor/assets/javascripts/codemirror/modes/markdown.js +231 -45
  51. data/vendor/assets/javascripts/codemirror/modes/{ocaml.js → mllike.js} +88 -13
  52. data/vendor/assets/javascripts/codemirror/modes/pegjs.js +5 -9
  53. data/vendor/assets/javascripts/codemirror/modes/php.js +6 -7
  54. data/vendor/assets/javascripts/codemirror/modes/python.js +6 -0
  55. data/vendor/assets/javascripts/codemirror/modes/r.js +5 -1
  56. data/vendor/assets/javascripts/codemirror/modes/rpm-spec.js +1 -1
  57. data/vendor/assets/javascripts/codemirror/modes/ruby.js +3 -1
  58. data/vendor/assets/javascripts/codemirror/modes/smalltalk.js +4 -2
  59. data/vendor/assets/javascripts/codemirror/modes/smartymixed.js +0 -2
  60. data/vendor/assets/javascripts/codemirror/modes/sql.js +5 -4
  61. data/vendor/assets/javascripts/codemirror/modes/xml.js +87 -100
  62. data/vendor/assets/stylesheets/codemirror/themes/mbo.css +1 -1
  63. data/vendor/assets/stylesheets/codemirror/themes/midnight.css +1 -1
  64. data/vendor/assets/stylesheets/codemirror/themes/pastel-on-dark.css +49 -0
  65. data/vendor/assets/stylesheets/codemirror/themes/the-matrix.css +1 -1
  66. metadata +3 -2
@@ -1,14 +1,11 @@
1
- CodeMirror.defineMode('ocaml', function() {
1
+ CodeMirror.defineMode('mllike', function(_config, parserConfig) {
2
2
 
3
3
  var words = {
4
- 'true': 'atom',
5
- 'false': 'atom',
6
4
  'let': 'keyword',
7
5
  'rec': 'keyword',
8
6
  'in': 'keyword',
9
7
  'of': 'keyword',
10
8
  'and': 'keyword',
11
- 'succ': 'keyword',
12
9
  'if': 'keyword',
13
10
  'then': 'keyword',
14
11
  'else': 'keyword',
@@ -25,17 +22,19 @@ CodeMirror.defineMode('ocaml', function() {
25
22
  'match': 'keyword',
26
23
  'with': 'keyword',
27
24
  'try': 'keyword',
28
- 'raise': 'keyword',
29
- 'begin': 'keyword',
30
- 'end': 'keyword',
31
25
  'open': 'builtin',
32
- 'trace': 'builtin',
33
26
  'ignore': 'builtin',
34
- 'exit': 'builtin',
35
- 'print_string': 'builtin',
36
- 'print_endline': 'builtin'
27
+ 'begin': 'keyword',
28
+ 'end': 'keyword'
37
29
  };
38
30
 
31
+ var extraWords = parserConfig.extraWords || {};
32
+ for (var prop in extraWords) {
33
+ if (extraWords.hasOwnProperty(prop)) {
34
+ words[prop] = parserConfig.extraWords[prop];
35
+ }
36
+ }
37
+
39
38
  function tokenBase(stream, state) {
40
39
  var ch = stream.next();
41
40
 
@@ -58,6 +57,10 @@ CodeMirror.defineMode('ocaml', function() {
58
57
  stream.eatWhile(/\w/);
59
58
  return 'quote';
60
59
  }
60
+ if (ch === '/' && parserConfig.slashComments && stream.eat('/')) {
61
+ stream.skipToEnd();
62
+ return 'comment';
63
+ }
61
64
  if (/\d/.test(ch)) {
62
65
  stream.eatWhile(/[\d]/);
63
66
  if (stream.eat('.')) {
@@ -109,8 +112,80 @@ CodeMirror.defineMode('ocaml', function() {
109
112
  },
110
113
 
111
114
  blockCommentStart: "(*",
112
- blockCommentEnd: "*)"
115
+ blockCommentEnd: "*)",
116
+ lineComment: parserConfig.slashComments ? "//" : null
113
117
  };
114
118
  });
115
119
 
116
- CodeMirror.defineMIME('text/x-ocaml', 'ocaml');
120
+ CodeMirror.defineMIME('text/x-ocaml', {
121
+ name: 'mllike',
122
+ extraWords: {
123
+ 'succ': 'keyword',
124
+ 'trace': 'builtin',
125
+ 'exit': 'builtin',
126
+ 'print_string': 'builtin',
127
+ 'print_endline': 'builtin',
128
+ 'true': 'atom',
129
+ 'false': 'atom',
130
+ 'raise': 'keyword'
131
+ }
132
+ });
133
+
134
+ CodeMirror.defineMIME('text/x-fsharp', {
135
+ name: 'mllike',
136
+ extraWords: {
137
+ 'abstract': 'keyword',
138
+ 'as': 'keyword',
139
+ 'assert': 'keyword',
140
+ 'base': 'keyword',
141
+ 'class': 'keyword',
142
+ 'default': 'keyword',
143
+ 'delegate': 'keyword',
144
+ 'downcast': 'keyword',
145
+ 'downto': 'keyword',
146
+ 'elif': 'keyword',
147
+ 'exception': 'keyword',
148
+ 'extern': 'keyword',
149
+ 'finally': 'keyword',
150
+ 'global': 'keyword',
151
+ 'inherit': 'keyword',
152
+ 'inline': 'keyword',
153
+ 'interface': 'keyword',
154
+ 'internal': 'keyword',
155
+ 'lazy': 'keyword',
156
+ 'let!': 'keyword',
157
+ 'member' : 'keyword',
158
+ 'module': 'keyword',
159
+ 'namespace': 'keyword',
160
+ 'new': 'keyword',
161
+ 'null': 'keyword',
162
+ 'override': 'keyword',
163
+ 'private': 'keyword',
164
+ 'public': 'keyword',
165
+ 'return': 'keyword',
166
+ 'return!': 'keyword',
167
+ 'select': 'keyword',
168
+ 'static': 'keyword',
169
+ 'struct': 'keyword',
170
+ 'upcast': 'keyword',
171
+ 'use': 'keyword',
172
+ 'use!': 'keyword',
173
+ 'val': 'keyword',
174
+ 'when': 'keyword',
175
+ 'yield': 'keyword',
176
+ 'yield!': 'keyword',
177
+
178
+ 'List': 'builtin',
179
+ 'Seq': 'builtin',
180
+ 'Map': 'builtin',
181
+ 'Set': 'builtin',
182
+ 'int': 'builtin',
183
+ 'string': 'builtin',
184
+ 'raise': 'builtin',
185
+ 'failwith': 'builtin',
186
+ 'not': 'builtin',
187
+ 'true': 'builtin',
188
+ 'false': 'builtin'
189
+ },
190
+ slashComments: true
191
+ });
@@ -54,15 +54,11 @@ CodeMirror.defineMode("pegjs", function (config) {
54
54
  }
55
55
  return "comment";
56
56
  } else if (state.inChracterClass) {
57
- if (stream.match(/^[^\]\\]+/)) {
58
- return;
59
- } else if (stream.match(/^\\./)) {
60
- return;
61
- } else {
62
- stream.next();
63
- state.inChracterClass = false;
64
- return 'bracket';
65
- }
57
+ while (state.inChracterClass && !stream.eol()) {
58
+ if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./))) {
59
+ state.inChracterClass = false;
60
+ }
61
+ }
66
62
  } else if (stream.peek() === '[') {
67
63
  stream.next();
68
64
  state.inChracterClass = true;
@@ -56,15 +56,15 @@
56
56
 
57
57
  function dispatch(stream, state) {
58
58
  var isPHP = state.curMode == phpMode;
59
- if (stream.sol() && state.pending != '"') state.pending = null;
59
+ if (stream.sol() && state.pending && state.pending != '"' && state.pending != "'") state.pending = null;
60
60
  if (!isPHP) {
61
61
  if (stream.match(/^<\?\w*/)) {
62
62
  state.curMode = phpMode;
63
63
  state.curState = state.php;
64
64
  return "meta";
65
65
  }
66
- if (state.pending == '"') {
67
- while (!stream.eol() && stream.next() != '"') {}
66
+ if (state.pending == '"' || state.pending == "'") {
67
+ while (!stream.eol() && stream.next() != state.pending) {}
68
68
  var style = "string";
69
69
  } else if (state.pending && stream.pos < state.pending.end) {
70
70
  stream.pos = state.pending.end;
@@ -72,10 +72,10 @@
72
72
  } else {
73
73
  var style = htmlMode.token(stream, state.curState);
74
74
  }
75
- state.pending = null;
76
- var cur = stream.current(), openPHP = cur.search(/<\?/);
75
+ if (state.pending) state.pending = null;
76
+ var cur = stream.current(), openPHP = cur.search(/<\?/), m;
77
77
  if (openPHP != -1) {
78
- if (style == "string" && /\"$/.test(cur) && !/\?>/.test(cur)) state.pending = '"';
78
+ if (style == "string" && (m = cur.match(/[\'\"]$/)) && !/\?>/.test(cur)) state.pending = m[0];
79
79
  else state.pending = {end: stream.pos, style: style};
80
80
  stream.backUp(cur.length - openPHP);
81
81
  }
@@ -117,7 +117,6 @@
117
117
  return state.curMode.indent(state.curState, textAfter);
118
118
  },
119
119
 
120
- electricChars: "/{}:",
121
120
  blockCommentStart: "/*",
122
121
  blockCommentEnd: "*/",
123
122
  lineComment: "//",
@@ -11,6 +11,7 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
11
11
  var doubleDelimiters = parserConf.doubleDelimiters || new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
12
12
  var tripleDelimiters = parserConf.tripleDelimiters || new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
13
13
  var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
14
+ var hangingIndent = parserConf.hangingIndent || parserConf.indentUnit;
14
15
 
15
16
  var wordOperators = wordRegexp(['and', 'or', 'not', 'is', 'in']);
16
17
  var commonkeywords = ['as', 'assert', 'break', 'class', 'continue',
@@ -211,6 +212,11 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
211
212
  break;
212
213
  }
213
214
  }
215
+ } else if (stream.match(/\s*($|#)/, false)) {
216
+ // An open paren/bracket/brace with only space or comments after it
217
+ // on the line will indent the next line a fixed amount, to make it
218
+ // easier to put arguments, list items, etc. on their own lines.
219
+ indentUnit = stream.indentation() + hangingIndent;
214
220
  } else {
215
221
  indentUnit = stream.column() + stream.current().length;
216
222
  }
@@ -36,7 +36,11 @@ CodeMirror.defineMode("r", function(config) {
36
36
  var word = stream.current();
37
37
  if (atoms.propertyIsEnumerable(word)) return "atom";
38
38
  if (keywords.propertyIsEnumerable(word)) {
39
- if (blockkeywords.propertyIsEnumerable(word)) curPunc = "block";
39
+ // Block keywords start new blocks, except 'else if', which only starts
40
+ // one new block for the 'if', no block for the 'else'.
41
+ if (blockkeywords.propertyIsEnumerable(word) &&
42
+ !stream.match(/\s*if(\s+|$)/, false))
43
+ curPunc = "block";
40
44
  return "keyword";
41
45
  }
42
46
  if (builtins.propertyIsEnumerable(word)) return "builtin";
@@ -4,7 +4,7 @@ CodeMirror.defineMode("spec", function() {
4
4
  var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/;
5
5
 
6
6
  var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\(\w+\))?|Obsoletes|Conflicts|Recommends|Source\d*|Patch\d*|ExclusiveArch|NoSource|Supplements):/;
7
- var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preun|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/;
7
+ var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preinstall|preun|postinstall|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/;
8
8
  var control_flow_complex = /^%(ifnarch|ifarch|if)/; // rpm control flow macros
9
9
  var control_flow_simple = /^%(else|endif)/; // rpm control flow macros
10
10
  var operators = /^(\!|\?|\<\=|\<|\>\=|\>|\=\=|\&\&|\|\|)/; // operators in control flow macros
@@ -12,7 +12,7 @@ CodeMirror.defineMode("ruby", function(config) {
12
12
  "caller", "lambda", "proc", "public", "protected", "private", "require", "load",
13
13
  "require_relative", "extend", "autoload", "__END__", "__FILE__", "__LINE__", "__dir__"
14
14
  ]);
15
- var indentWords = wordObj(["def", "class", "case", "for", "while", "do", "module", "then",
15
+ var indentWords = wordObj(["def", "class", "case", "for", "while", "module", "then",
16
16
  "catch", "loop", "proc", "begin"]);
17
17
  var dedentWords = wordObj(["end", "until"]);
18
18
  var matching = {"[": "]", "{": "}", "(": ")"};
@@ -214,6 +214,8 @@ CodeMirror.defineMode("ruby", function(config) {
214
214
  else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent";
215
215
  else if ((word == "if" || word == "unless") && stream.column() == stream.indentation())
216
216
  kwtype = "indent";
217
+ else if (word == "do" && state.context.indented < state.indented)
218
+ kwtype = "indent";
217
219
  }
218
220
  if (curPunc || (style && style != "comment")) state.lastTok = word || curPunc || style;
219
221
  if (curPunc == "|") state.varList = !state.varList;
@@ -40,8 +40,10 @@ CodeMirror.defineMode('smalltalk', function(config) {
40
40
  stream.next();
41
41
  token = nextSymbol(stream, new Context(nextSymbol, context));
42
42
  } else {
43
- stream.eatWhile(/[^ .\[\]()]/);
44
- token.name = 'string-2';
43
+ if (stream.eatWhile(/[^ .{}\[\]()]/))
44
+ token.name = 'string-2';
45
+ else
46
+ token.name = 'meta';
45
47
  }
46
48
 
47
49
  } else if (aChar === '$') {
@@ -159,8 +159,6 @@ CodeMirror.defineMode("smartymixed", function(config) {
159
159
  return htmlMixedMode.indent(state.htmlMixedState, textAfter);
160
160
  },
161
161
 
162
- electricChars: "/{}:",
163
-
164
162
  innerMode: function(state) {
165
163
  return {
166
164
  state: state.localState || state.htmlMixedState,
@@ -177,9 +177,10 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {
177
177
 
178
178
  indent: function(state, textAfter) {
179
179
  var cx = state.context;
180
- if (!cx) return CodeMirror.Pass;
181
- if (cx.align) return cx.col + (textAfter.charAt(0) == cx.type ? 0 : 1);
182
- else return cx.indent + config.indentUnit;
180
+ if (!cx) return 0;
181
+ var closing = textAfter.charAt(0) == cx.type;
182
+ if (cx.align) return cx.col + (closing ? 0 : 1);
183
+ else return cx.indent + (closing ? 0 : config.indentUnit);
183
184
  },
184
185
 
185
186
  blockCommentStart: "/*",
@@ -326,7 +327,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {
326
327
  name: "sql",
327
328
  client: set("appinfo arraysize autocommit autoprint autorecovery autotrace blockterminator break btitle cmdsep colsep compatibility compute concat copycommit copytypecheck define describe echo editfile embedded escape exec execute feedback flagger flush heading headsep instance linesize lno loboffset logsource long longchunksize markup native newpage numformat numwidth pagesize pause pno recsep recsepchar release repfooter repheader serveroutput shiftinout show showmode size spool sqlblanklines sqlcase sqlcode sqlcontinue sqlnumber sqlpluscompatibility sqlprefix sqlprompt sqlterminator suffix tab term termout time timing trimout trimspool ttitle underline verify version wrap"),
328
329
  keywords: set("abort accept access add all alter and any array arraylen as asc assert assign at attributes audit authorization avg base_table begin between binary_integer body boolean by case cast char char_base check close cluster clusters colauth column comment commit compress connect connected constant constraint crash create current currval cursor data_base database date dba deallocate debugoff debugon decimal declare default definition delay delete desc digits dispose distinct do drop else elsif enable end entry escape exception exception_init exchange exclusive exists exit external fast fetch file for force form from function generic goto grant group having identified if immediate in increment index indexes indicator initial initrans insert interface intersect into is key level library like limited local lock log logging long loop master maxextents maxtrans member minextents minus mislabel mode modify multiset new next no noaudit nocompress nologging noparallel not nowait number_base object of off offline on online only open option or order out package parallel partition pctfree pctincrease pctused pls_integer positive positiven pragma primary prior private privileges procedure public raise range raw read rebuild record ref references refresh release rename replace resource restrict return returning reverse revoke rollback row rowid rowlabel rownum rows run savepoint schema segment select separate session set share snapshot some space split sql start statement storage subtype successful synonym tabauth table tables tablespace task terminate then to trigger truncate type union unique unlimited unrecoverable unusable update use using validate value values variable view views when whenever where while with work"),
329
- builtin: set("bfile blob character clob dec float int integer mlslabel natural naturaln nchar nclob number numeric nvarchar2 real rowtype signtype smallint string varchar varchar2 abs acos add_months ascii asin atan atan2 average bfilename ceil chartorowid chr concat convert cos cosh count decode deref dual dump dup_val_on_index empty error exp false floor found glb greatest hextoraw initcap instr instrb isopen last_day least lenght lenghtb ln lower lpad ltrim lub make_ref max min mod months_between new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null nvl others power rawtohex reftohex round rowcount rowidtochar rpad rtrim sign sin sinh soundex sqlcode sqlerrm sqrt stddev substr substrb sum sysdate tan tanh to_char to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid upper user userenv variance vsize"),
330
+ builtin: set("abs acos add_months ascii asin atan atan2 average bfile bfilename bit blob ceil character chartorowid chr clob concat convert cos cosh count dec decode deref dual dump dup_val_on_index empty error exp false float floor found glb greatest hextoraw initcap instr instrb int integer isopen last_day least lenght lenghtb ln lower lpad ltrim lub make_ref max min mlslabel mod months_between natural naturaln nchar nclob new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null number numeric nvarchar2 nvl others power rawtohex real reftohex round rowcount rowidtochar rowtype rpad rtrim sign signtype sin sinh smallint soundex sqlcode sqlerrm sqrt stddev string substr substrb sum sysdate tan tanh to_char text to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid upper user userenv varchar varchar2 variance varying vsize xml"),
330
331
  operatorChars: /^[*+\-%<>!=~]/,
331
332
  dateSQL: set("date time timestamp"),
332
333
  support: set("doubleQuote nCharCast zerolessFloat binaryNumber hexNumber")
@@ -45,7 +45,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
45
45
  var alignCDATA = parserConfig.alignCDATA;
46
46
 
47
47
  // Return variables for tokenizers
48
- var tagName, type;
48
+ var tagName, type, setStyle;
49
49
 
50
50
  function inText(stream, state) {
51
51
  function chain(parser) {
@@ -110,6 +110,8 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
110
110
  return null;
111
111
  } else if (ch == "<") {
112
112
  state.tokenize = inText;
113
+ state.state = baseState;
114
+ state.tagName = state.tagStart = null;
113
115
  var next = state.tokenize(stream, state);
114
116
  return next ? next + " error" : "error";
115
117
  } else if (/[\'\"]/.test(ch)) {
@@ -169,139 +171,124 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
169
171
  };
170
172
  }
171
173
 
172
- var curState, curStream, setStyle;
173
- function pass() {
174
- for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
174
+ function Context(state, tagName, startOfLine) {
175
+ this.prev = state.context;
176
+ this.tagName = tagName;
177
+ this.indent = state.indented;
178
+ this.startOfLine = startOfLine;
179
+ if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
180
+ this.noIndent = true;
175
181
  }
176
- function cont() {
177
- pass.apply(null, arguments);
178
- return true;
182
+ function popContext(state) {
183
+ if (state.context) state.context = state.context.prev;
179
184
  }
180
-
181
- function pushContext(tagName, startOfLine) {
182
- var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent);
183
- curState.context = {
184
- prev: curState.context,
185
- tagName: tagName,
186
- indent: curState.indented,
187
- startOfLine: startOfLine,
188
- noIndent: noIndent
189
- };
190
- }
191
- function popContext() {
192
- if (curState.context) curState.context = curState.context.prev;
185
+ function maybePopContext(state, nextTagName) {
186
+ var parentTagName;
187
+ while (true) {
188
+ if (!state.context) {
189
+ return;
190
+ }
191
+ parentTagName = state.context.tagName.toLowerCase();
192
+ if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
193
+ !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
194
+ return;
195
+ }
196
+ popContext(state);
197
+ }
193
198
  }
194
199
 
195
- function element(type) {
200
+ function baseState(type, stream, state) {
196
201
  if (type == "openTag") {
197
- curState.tagName = tagName;
198
- curState.tagStart = curStream.column();
199
- return cont(attributes, endtag(curState.startOfLine));
202
+ state.tagName = tagName;
203
+ state.tagStart = stream.column();
204
+ return attrState;
200
205
  } else if (type == "closeTag") {
201
206
  var err = false;
202
- if (curState.context) {
203
- if (curState.context.tagName != tagName) {
204
- if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) {
205
- popContext();
206
- }
207
- err = !curState.context || curState.context.tagName != tagName;
207
+ if (state.context) {
208
+ if (state.context.tagName != tagName) {
209
+ if (Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName.toLowerCase()))
210
+ popContext(state);
211
+ err = !state.context || state.context.tagName != tagName;
208
212
  }
209
213
  } else {
210
214
  err = true;
211
215
  }
212
216
  if (err) setStyle = "error";
213
- return cont(endclosetag(err));
217
+ return err ? closeStateErr : closeState;
218
+ } else {
219
+ return baseState;
214
220
  }
215
- return cont();
216
- }
217
- function endtag(startOfLine) {
218
- return function(type) {
219
- var tagName = curState.tagName;
220
- curState.tagName = curState.tagStart = null;
221
- if (type == "selfcloseTag" ||
222
- (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(tagName.toLowerCase()))) {
223
- maybePopContext(tagName.toLowerCase());
224
- return cont();
225
- }
226
- if (type == "endTag") {
227
- maybePopContext(tagName.toLowerCase());
228
- pushContext(tagName, startOfLine);
229
- return cont();
230
- }
231
- return cont();
232
- };
233
221
  }
234
- function endclosetag(err) {
235
- return function(type) {
236
- if (err) setStyle = "error";
237
- if (type == "endTag") { popContext(); return cont(); }
222
+ function closeState(type, _stream, state) {
223
+ if (type != "endTag") {
238
224
  setStyle = "error";
239
- return cont(arguments.callee);
240
- };
241
- }
242
- function maybePopContext(nextTagName) {
243
- var parentTagName;
244
- while (true) {
245
- if (!curState.context) {
246
- return;
247
- }
248
- parentTagName = curState.context.tagName.toLowerCase();
249
- if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
250
- !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
251
- return;
252
- }
253
- popContext();
225
+ return closeState;
254
226
  }
227
+ popContext(state);
228
+ return baseState;
229
+ }
230
+ function closeStateErr(type, stream, state) {
231
+ setStyle = "error";
232
+ return closeState(type, stream, state);
255
233
  }
256
234
 
257
- function attributes(type) {
258
- if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);}
259
- if (type == "endTag" || type == "selfcloseTag") return pass();
235
+ function attrState(type, _stream, state) {
236
+ if (type == "word") {
237
+ setStyle = "attribute";
238
+ return attrEqState;
239
+ } else if (type == "endTag" || type == "selfcloseTag") {
240
+ var tagName = state.tagName, tagStart = state.tagStart;
241
+ state.tagName = state.tagStart = null;
242
+ if (type == "selfcloseTag" ||
243
+ Kludges.autoSelfClosers.hasOwnProperty(tagName.toLowerCase())) {
244
+ maybePopContext(state, tagName.toLowerCase());
245
+ } else {
246
+ maybePopContext(state, tagName.toLowerCase());
247
+ state.context = new Context(state, tagName, tagStart == state.indented);
248
+ }
249
+ return baseState;
250
+ }
260
251
  setStyle = "error";
261
- return cont(attributes);
252
+ return attrState;
262
253
  }
263
- function attribute(type) {
264
- if (type == "equals") return cont(attvalue, attributes);
254
+ function attrEqState(type, stream, state) {
255
+ if (type == "equals") return attrValueState;
265
256
  if (!Kludges.allowMissing) setStyle = "error";
266
- else if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);}
267
- return (type == "endTag" || type == "selfcloseTag") ? pass() : cont();
257
+ return attrState(type, stream, state);
268
258
  }
269
- function attvalue(type) {
270
- if (type == "string") return cont(attvaluemaybe);
271
- if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();}
259
+ function attrValueState(type, stream, state) {
260
+ if (type == "string") return attrContinuedState;
261
+ if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;}
272
262
  setStyle = "error";
273
- return (type == "endTag" || type == "selfCloseTag") ? pass() : cont();
263
+ return attrState(type, stream, state);
274
264
  }
275
- function attvaluemaybe(type) {
276
- if (type == "string") return cont(attvaluemaybe);
277
- else return pass();
265
+ function attrContinuedState(type, stream, state) {
266
+ if (type == "string") return attrContinuedState;
267
+ return attrState(type, stream, state);
278
268
  }
279
269
 
280
270
  return {
281
271
  startState: function() {
282
- return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, tagStart: null, context: null};
272
+ return {tokenize: inText,
273
+ state: baseState,
274
+ indented: 0,
275
+ tagName: null, tagStart: null,
276
+ context: null};
283
277
  },
284
278
 
285
279
  token: function(stream, state) {
286
- if (!state.tagName && stream.sol()) {
287
- state.startOfLine = true;
280
+ if (!state.tagName && stream.sol())
288
281
  state.indented = stream.indentation();
289
- }
290
- if (stream.eatSpace()) return null;
291
282
 
292
- setStyle = type = tagName = null;
283
+ if (stream.eatSpace()) return null;
284
+ tagName = type = null;
293
285
  var style = state.tokenize(stream, state);
294
- state.type = type;
295
286
  if ((style || type) && style != "comment") {
296
- curState = state; curStream = stream;
297
- while (true) {
298
- var comb = state.cc.pop() || element;
299
- if (comb(type || style)) break;
300
- }
287
+ setStyle = null;
288
+ state.state = state.state(type || style, stream, state);
289
+ if (setStyle)
290
+ style = setStyle == "error" ? style + " error" : setStyle;
301
291
  }
302
- state.startOfLine = false;
303
- if (setStyle)
304
- style = setStyle == "error" ? style + " error" : setStyle;
305
292
  return style;
306
293
  },
307
294
 
@@ -311,8 +298,8 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
311
298
  if (state.tokenize.isInAttribute) {
312
299
  return state.stringStartCol + 1;
313
300
  }
314
- if ((state.tokenize != inTag && state.tokenize != inText) ||
315
- context && context.noIndent)
301
+ if (context && context.noIndent) return CodeMirror.Pass;
302
+ if (state.tokenize != inTag && state.tokenize != inText)
316
303
  return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
317
304
  // Indent the starts of attribute names.
318
305
  if (state.tagName) {