codemirror-rails 4.8 → 4.9

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +24 -6
  3. data/lib/codemirror/rails/version.rb +2 -2
  4. data/vendor/assets/javascripts/codemirror.js +289 -184
  5. data/vendor/assets/javascripts/codemirror/addons/dialog/dialog.js +1 -1
  6. data/vendor/assets/javascripts/codemirror/addons/display/panel.js +94 -0
  7. data/vendor/assets/javascripts/codemirror/addons/edit/continuelist.js +4 -4
  8. data/vendor/assets/javascripts/codemirror/addons/hint/anyword-hint.js +1 -2
  9. data/vendor/assets/javascripts/codemirror/addons/hint/css-hint.js +1 -1
  10. data/vendor/assets/javascripts/codemirror/addons/hint/html-hint.js +1 -1
  11. data/vendor/assets/javascripts/codemirror/addons/hint/javascript-hint.js +8 -3
  12. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +1 -1
  13. data/vendor/assets/javascripts/codemirror/addons/hint/sql-hint.js +7 -4
  14. data/vendor/assets/javascripts/codemirror/addons/hint/xml-hint.js +3 -4
  15. data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +170 -63
  16. data/vendor/assets/javascripts/codemirror/addons/mode/simple.js +11 -8
  17. data/vendor/assets/javascripts/codemirror/addons/scroll/annotatescrollbar.js +76 -0
  18. data/vendor/assets/javascripts/codemirror/addons/scroll/simplescrollbars.js +139 -0
  19. data/vendor/assets/javascripts/codemirror/addons/search/matchesonscrollbar.js +90 -0
  20. data/vendor/assets/javascripts/codemirror/addons/search/search.js +9 -4
  21. data/vendor/assets/javascripts/codemirror/addons/tern/tern.js +5 -3
  22. data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +25 -7
  23. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +181 -109
  24. data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +2 -2
  25. data/vendor/assets/javascripts/codemirror/modes/commonlisp.js +5 -3
  26. data/vendor/assets/javascripts/codemirror/modes/cypher.js +1 -1
  27. data/vendor/assets/javascripts/codemirror/modes/dart.js +50 -0
  28. data/vendor/assets/javascripts/codemirror/modes/dockerfile.js +5 -9
  29. data/vendor/assets/javascripts/codemirror/modes/ebnf.js +195 -0
  30. data/vendor/assets/javascripts/codemirror/modes/javascript.js +2 -0
  31. data/vendor/assets/javascripts/codemirror/modes/markdown.js +3 -3
  32. data/vendor/assets/javascripts/codemirror/modes/puppet.js +2 -2
  33. data/vendor/assets/javascripts/codemirror/modes/shell.js +2 -1
  34. data/vendor/assets/javascripts/codemirror/modes/soy.js +198 -0
  35. data/vendor/assets/javascripts/codemirror/modes/spreadsheet.js +109 -0
  36. data/vendor/assets/javascripts/codemirror/modes/stex.js +4 -6
  37. data/vendor/assets/javascripts/codemirror/modes/textile.js +392 -476
  38. data/vendor/assets/javascripts/codemirror/modes/turtle.js +3 -1
  39. data/vendor/assets/stylesheets/codemirror.css +2 -11
  40. data/vendor/assets/stylesheets/codemirror/addons/merge/merge.css +14 -0
  41. data/vendor/assets/stylesheets/codemirror/addons/scroll/simplescrollbars.css +66 -0
  42. data/vendor/assets/stylesheets/codemirror/addons/search/matchesonscrollbar.css +8 -0
  43. data/vendor/assets/stylesheets/codemirror/themes/tomorrow-night-bright.css +35 -0
  44. data/vendor/assets/stylesheets/codemirror/themes/zenburn.css +37 -0
  45. metadata +14 -3
  46. data/vendor/assets/javascripts/codemirror/addons/hint/python-hint.js +0 -102
@@ -62,7 +62,7 @@
62
62
  var curPunc;
63
63
  var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "right", "round", "rtrim", "shortestPath", "sign", "sin", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "trim", "type", "upper"]);
64
64
  var preds = wordRegexp(["all", "and", "any", "has", "in", "none", "not", "or", "single", "xor"]);
65
- var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "distinct", "drop", "else", "end", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "remove", "return", "scan", "set", "skip", "start", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with"]);
65
+ var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "distinct", "drop", "else", "end", "explain", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "profile", "remove", "return", "scan", "set", "skip", "start", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with"]);
66
66
  var operatorChars = /[*+\-<>=&|~%^]/;
67
67
 
68
68
  return {
@@ -0,0 +1,50 @@
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"), require("../clike/clike"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror", "../clike/clike"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ var keywords = ("this super static final const abstract class extends external factory " +
15
+ "implements get native operator set typedef with enum throw rethrow " +
16
+ "assert break case continue default in return new deferred async await " +
17
+ "try catch finally do else for if switch while import library export " +
18
+ "part of show hide is").split(" ");
19
+ var blockKeywords = "try catch finally do else for if switch while".split(" ");
20
+ var atoms = "true false null".split(" ");
21
+ var builtins = "void bool num int double dynamic var String".split(" ");
22
+
23
+ function set(words) {
24
+ var obj = {};
25
+ for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
26
+ return obj;
27
+ }
28
+
29
+ CodeMirror.defineMIME("application/dart", {
30
+ name: "clike",
31
+ keywords: set(keywords),
32
+ multiLineStrings: true,
33
+ blockKeywords: set(blockKeywords),
34
+ builtin: set(builtins),
35
+ atoms: set(atoms),
36
+ hooks: {
37
+ "@": function(stream) {
38
+ stream.eatWhile(/[\w\$_]/);
39
+ return "meta";
40
+ }
41
+ }
42
+ });
43
+
44
+ CodeMirror.registerHelper("hintWords", "application/dart", keywords.concat(atoms).concat(builtins));
45
+
46
+ // This is needed to make loading through meta.js work.
47
+ CodeMirror.defineMode("dart", function(conf) {
48
+ return CodeMirror.getMode(conf, "application/dart");
49
+ }, "clike");
50
+ });
@@ -24,14 +24,12 @@
24
24
  // Block comment: This is a line starting with a comment
25
25
  {
26
26
  regex: /#.*$/,
27
- token: "comment",
28
- next: "start"
27
+ token: "comment"
29
28
  },
30
29
  // Highlight an instruction without any arguments (for convenience)
31
30
  {
32
31
  regex: instructionOnlyLine,
33
- token: "variable-2",
34
- next: "start"
32
+ token: "variable-2"
35
33
  },
36
34
  // Highlight an instruction followed by arguments
37
35
  {
@@ -39,10 +37,9 @@
39
37
  token: ["variable-2", null],
40
38
  next: "arguments"
41
39
  },
42
- // Fail-safe return to start
43
40
  {
44
- token: null,
45
- next: "start"
41
+ regex: /./,
42
+ token: null
46
43
  }
47
44
  ],
48
45
  arguments: [
@@ -54,8 +51,7 @@
54
51
  },
55
52
  {
56
53
  regex: /[^#]+\\$/,
57
- token: null,
58
- next: "arguments"
54
+ token: null
59
55
  },
60
56
  {
61
57
  // Match everything except for the inline comment
@@ -0,0 +1,195 @@
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ CodeMirror.defineMode("ebnf", function (config) {
15
+ var commentType = {slash: 0, parenthesis: 1};
16
+ var stateType = {comment: 0, _string: 1, characterClass: 2};
17
+ var bracesMode = null;
18
+
19
+ if (config.bracesMode)
20
+ bracesMode = CodeMirror.getMode(config, config.bracesMode);
21
+
22
+ return {
23
+ startState: function () {
24
+ return {
25
+ stringType: null,
26
+ commentType: null,
27
+ braced: 0,
28
+ lhs: true,
29
+ localState: null,
30
+ stack: [],
31
+ inDefinition: false
32
+ };
33
+ },
34
+ token: function (stream, state) {
35
+ if (!stream) return;
36
+
37
+ //check for state changes
38
+ if (state.stack.length === 0) {
39
+ //strings
40
+ if ((stream.peek() == '"') || (stream.peek() == "'")) {
41
+ state.stringType = stream.peek();
42
+ stream.next(); // Skip quote
43
+ state.stack.unshift(stateType._string);
44
+ } else if (stream.match(/^\/\*/)) { //comments starting with /*
45
+ state.stack.unshift(stateType.comment);
46
+ state.commentType = commentType.slash;
47
+ } else if (stream.match(/^\(\*/)) { //comments starting with (*
48
+ state.stack.unshift(stateType.comment);
49
+ state.commentType = commentType.parenthesis;
50
+ }
51
+ }
52
+
53
+ //return state
54
+ //stack has
55
+ switch (state.stack[0]) {
56
+ case stateType._string:
57
+ while (state.stack[0] === stateType._string && !stream.eol()) {
58
+ if (stream.peek() === state.stringType) {
59
+ stream.next(); // Skip quote
60
+ state.stack.shift(); // Clear flag
61
+ } else if (stream.peek() === "\\") {
62
+ stream.next();
63
+ stream.next();
64
+ } else {
65
+ stream.match(/^.[^\\\"\']*/);
66
+ }
67
+ }
68
+ return state.lhs ? "property string" : "string"; // Token style
69
+
70
+ case stateType.comment:
71
+ while (state.stack[0] === stateType.comment && !stream.eol()) {
72
+ if (state.commentType === commentType.slash && stream.match(/\*\//)) {
73
+ state.stack.shift(); // Clear flag
74
+ state.commentType = null;
75
+ } else if (state.commentType === commentType.parenthesis && stream.match(/\*\)/)) {
76
+ state.stack.shift(); // Clear flag
77
+ state.commentType = null;
78
+ } else {
79
+ stream.match(/^.[^\*]*/);
80
+ }
81
+ }
82
+ return "comment";
83
+
84
+ case stateType.characterClass:
85
+ while (state.stack[0] === stateType.characterClass && !stream.eol()) {
86
+ if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./))) {
87
+ state.stack.shift();
88
+ }
89
+ }
90
+ return "operator";
91
+ }
92
+
93
+ var peek = stream.peek();
94
+
95
+ if (bracesMode !== null && (state.braced || peek === "{")) {
96
+ if (state.localState === null)
97
+ state.localState = bracesMode.startState();
98
+
99
+ var token = bracesMode.token(stream, state.localState),
100
+ text = stream.current();
101
+
102
+ if (!token) {
103
+ for (var i = 0; i < text.length; i++) {
104
+ if (text[i] === "{") {
105
+ if (state.braced === 0) {
106
+ token = "matchingbracket";
107
+ }
108
+ state.braced++;
109
+ } else if (text[i] === "}") {
110
+ state.braced--;
111
+ if (state.braced === 0) {
112
+ token = "matchingbracket";
113
+ }
114
+ }
115
+ }
116
+ }
117
+ return token;
118
+ }
119
+
120
+ //no stack
121
+ switch (peek) {
122
+ case "[":
123
+ stream.next();
124
+ state.stack.unshift(stateType.characterClass);
125
+ return "bracket";
126
+ case ":":
127
+ case "|":
128
+ case ";":
129
+ stream.next();
130
+ return "operator";
131
+ case "%":
132
+ if (stream.match("%%")) {
133
+ return "header";
134
+ } else if (stream.match(/[%][A-Za-z]+/)) {
135
+ return "keyword";
136
+ } else if (stream.match(/[%][}]/)) {
137
+ return "matchingbracket";
138
+ }
139
+ break;
140
+ case "/":
141
+ if (stream.match(/[\/][A-Za-z]+/)) {
142
+ return "keyword";
143
+ }
144
+ case "\\":
145
+ if (stream.match(/[\][a-z]+/)) {
146
+ return "string-2";
147
+ }
148
+ case ".":
149
+ if (stream.match(".")) {
150
+ return "atom";
151
+ }
152
+ case "*":
153
+ case "-":
154
+ case "+":
155
+ case "^":
156
+ if (stream.match(peek)) {
157
+ return "atom";
158
+ }
159
+ case "$":
160
+ if (stream.match("$$")) {
161
+ return "builtin";
162
+ } else if (stream.match(/[$][0-9]+/)) {
163
+ return "variable-3";
164
+ }
165
+ case "<":
166
+ if (stream.match(/<<[a-zA-Z_]+>>/)) {
167
+ return "builtin";
168
+ }
169
+ }
170
+
171
+ if (stream.match(/^\/\//)) {
172
+ stream.skipToEnd();
173
+ return "comment";
174
+ } else if (stream.match(/return/)) {
175
+ return "operator";
176
+ } else if (stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/)) {
177
+ if (stream.match(/(?=[\(.])/)) {
178
+ return "variable";
179
+ } else if (stream.match(/(?=[\s\n]*[:=])/)) {
180
+ return "def";
181
+ }
182
+ return "variable-2";
183
+ } else if (["[", "]", "(", ")"].indexOf(stream.peek()) != -1) {
184
+ stream.next();
185
+ return "bracket";
186
+ } else if (!stream.eatSpace()) {
187
+ stream.next();
188
+ }
189
+ return null;
190
+ }
191
+ };
192
+ });
193
+
194
+ CodeMirror.defineMIME("text/x-ebnf", "ebnf");
195
+ });
@@ -205,6 +205,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
205
205
  ++depth;
206
206
  } else if (wordRE.test(ch)) {
207
207
  sawSomething = true;
208
+ } else if (/["'\/]/.test(ch)) {
209
+ return;
208
210
  } else if (sawSomething && !depth) {
209
211
  ++pos;
210
212
  break;
@@ -3,7 +3,7 @@
3
3
 
4
4
  (function(mod) {
5
5
  if (typeof exports == "object" && typeof module == "object") // CommonJS
6
- mod(require("../../lib/codemirror", require("../xml/xml"), require("../meta")));
6
+ mod(require("../../lib/codemirror"), require("../xml/xml"), require("../meta"));
7
7
  else if (typeof define == "function" && define.amd) // AMD
8
8
  define(["../../lib/codemirror", "../xml/xml", "../meta"], mod);
9
9
  else // Plain browser env
@@ -396,13 +396,13 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
396
396
  return image;
397
397
  }
398
398
 
399
- if (ch === '[' && stream.match(/.*\](\(| ?\[)/, false)) {
399
+ if (ch === '[' && stream.match(/.*\](\(.*\)| ?\[.*\])/, false)) {
400
400
  state.linkText = true;
401
401
  if (modeCfg.highlightFormatting) state.formatting = "link";
402
402
  return getType(state);
403
403
  }
404
404
 
405
- if (ch === ']' && state.linkText) {
405
+ if (ch === ']' && state.linkText && stream.match(/\(.*\)| ?\[.*\]/, false)) {
406
406
  if (modeCfg.highlightFormatting) state.formatting = "link";
407
407
  var type = getType(state);
408
408
  state.linkText = false;
@@ -140,11 +140,11 @@ CodeMirror.defineMode("puppet", function () {
140
140
  return words[word];
141
141
  }
142
142
  // Is there a match on a reference?
143
- if (/(\s+)?[A-Z]/.test(word)) {
143
+ if (/(^|\s+)[A-Z][\w:_]+/.test(word)) {
144
144
  // Negate the next()
145
145
  stream.backUp(1);
146
146
  // Match the full reference
147
- stream.match(/(\s+)?[A-Z][\w:_]+/);
147
+ stream.match(/(^|\s+)[A-Z][\w:_]+/);
148
148
  return 'def';
149
149
  }
150
150
  // Have we matched the prior resource regex?
@@ -129,7 +129,8 @@ CodeMirror.defineMode('shell', function() {
129
129
  token: function(stream, state) {
130
130
  return tokenize(stream, state);
131
131
  },
132
- lineComment: '#'
132
+ lineComment: '#',
133
+ fold: "brace"
133
134
  };
134
135
  });
135
136
 
@@ -0,0 +1,198 @@
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror", "../htmlmixed/htmlmixed"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ var indentingTags = ["template", "literal", "msg", "fallbackmsg", "let", "if", "elseif",
15
+ "else", "switch", "case", "default", "foreach", "ifempty", "for",
16
+ "call", "param", "deltemplate", "delcall", "log"];
17
+
18
+ CodeMirror.defineMode("soy", function(config) {
19
+ var textMode = CodeMirror.getMode(config, "text/plain");
20
+ var modes = {
21
+ html: CodeMirror.getMode(config, {name: "text/html", multilineTagIndentFactor: 2, multilineTagIndentPastTag: false}),
22
+ attributes: textMode,
23
+ text: textMode,
24
+ uri: textMode,
25
+ css: CodeMirror.getMode(config, "text/css"),
26
+ js: CodeMirror.getMode(config, {name: "text/javascript", statementIndent: 2 * config.indentUnit})
27
+ };
28
+
29
+ function last(array) {
30
+ return array[array.length - 1];
31
+ }
32
+
33
+ function tokenUntil(stream, state, untilRegExp) {
34
+ var oldString = stream.string;
35
+ var match = untilRegExp.exec(oldString.substr(stream.pos));
36
+ if (match) {
37
+ // We don't use backUp because it backs up just the position, not the state.
38
+ // This uses an undocumented API.
39
+ stream.string = oldString.substr(0, stream.pos + match.index);
40
+ }
41
+ var result = stream.hideFirstChars(state.indent, function() {
42
+ return state.localMode.token(stream, state.localState);
43
+ });
44
+ stream.string = oldString;
45
+ return result;
46
+ }
47
+
48
+ return {
49
+ startState: function() {
50
+ return {
51
+ kind: [],
52
+ kindTag: [],
53
+ soyState: [],
54
+ indent: 0,
55
+ localMode: modes.html,
56
+ localState: CodeMirror.startState(modes.html)
57
+ };
58
+ },
59
+
60
+ copyState: function(state) {
61
+ return {
62
+ tag: state.tag, // Last seen Soy tag.
63
+ kind: state.kind.concat([]), // Values of kind="" attributes.
64
+ kindTag: state.kindTag.concat([]), // Opened tags with kind="" attributes.
65
+ soyState: state.soyState.concat([]),
66
+ indent: state.indent, // Indentation of the following line.
67
+ localMode: state.localMode,
68
+ localState: CodeMirror.copyState(state.localMode, state.localState)
69
+ };
70
+ },
71
+
72
+ token: function(stream, state) {
73
+ var match;
74
+
75
+ switch (last(state.soyState)) {
76
+ case "comment":
77
+ if (stream.match(/^.*?\*\//)) {
78
+ state.soyState.pop();
79
+ } else {
80
+ stream.skipToEnd();
81
+ }
82
+ return "comment";
83
+
84
+ case "variable":
85
+ if (stream.match(/^}/)) {
86
+ state.indent -= 2 * config.indentUnit;
87
+ state.soyState.pop();
88
+ return "variable-2";
89
+ }
90
+ stream.next();
91
+ return null;
92
+
93
+ case "tag":
94
+ if (stream.match(/^\/?}/)) {
95
+ if (state.tag == "/template" || state.tag == "/deltemplate") state.indent = 0;
96
+ else state.indent -= (stream.current() == "/}" || indentingTags.indexOf(state.tag) == -1 ? 2 : 1) * config.indentUnit;
97
+ state.soyState.pop();
98
+ return "keyword";
99
+ } else if (stream.match(/^(\w+)(?==)/)) {
100
+ if (stream.current() == "kind" && (match = stream.match(/^="([^"]+)/, false))) {
101
+ var kind = match[1];
102
+ state.kind.push(kind);
103
+ state.kindTag.push(state.tag);
104
+ state.localMode = modes[kind] || modes.html;
105
+ state.localState = CodeMirror.startState(state.localMode);
106
+ }
107
+ return "attribute";
108
+ } else if (stream.match(/^"/)) {
109
+ state.soyState.push("string");
110
+ return "string";
111
+ }
112
+ stream.next();
113
+ return null;
114
+
115
+ case "literal":
116
+ if (stream.match(/^(?=\{\/literal})/)) {
117
+ state.indent -= config.indentUnit;
118
+ state.soyState.pop();
119
+ return this.token(stream, state);
120
+ }
121
+ return tokenUntil(stream, state, /\{\/literal}/);
122
+
123
+ case "string":
124
+ if (stream.match(/^.*?"/)) {
125
+ state.soyState.pop();
126
+ } else {
127
+ stream.skipToEnd();
128
+ }
129
+ return "string";
130
+ }
131
+
132
+ if (stream.match(/^\/\*/)) {
133
+ state.soyState.push("comment");
134
+ return "comment";
135
+ } else if (stream.match(stream.sol() ? /^\s*\/\/.*/ : /^\s+\/\/.*/)) {
136
+ return "comment";
137
+ } else if (stream.match(/^\{\$\w*/)) {
138
+ state.indent += 2 * config.indentUnit;
139
+ state.soyState.push("variable");
140
+ return "variable-2";
141
+ } else if (stream.match(/^\{literal}/)) {
142
+ state.indent += config.indentUnit;
143
+ state.soyState.push("literal");
144
+ return "keyword";
145
+ } else if (match = stream.match(/^\{([\/@\\]?\w*)/)) {
146
+ if (match[1] != "/switch")
147
+ state.indent += (/^(\/|(else|elseif|case|default)$)/.test(match[1]) && state.tag != "switch" ? 1 : 2) * config.indentUnit;
148
+ state.tag = match[1];
149
+ if (state.tag == "/" + last(state.kindTag)) {
150
+ // We found the tag that opened the current kind="".
151
+ state.kind.pop();
152
+ state.kindTag.pop();
153
+ state.localMode = modes[last(state.kind)] || modes.html;
154
+ state.localState = CodeMirror.startState(state.localMode);
155
+ }
156
+ state.soyState.push("tag");
157
+ return "keyword";
158
+ }
159
+
160
+ return tokenUntil(stream, state, /\{|\s+\/\/|\/\*/);
161
+ },
162
+
163
+ indent: function(state, textAfter) {
164
+ var indent = state.indent, top = last(state.soyState);
165
+ if (top == "comment") return CodeMirror.Pass;
166
+
167
+ if (top == "literal") {
168
+ if (/^\{\/literal}/.test(textAfter)) indent -= config.indentUnit;
169
+ } else {
170
+ if (/^\s*\{\/(template|deltemplate)\b/.test(textAfter)) return 0;
171
+ if (/^\{(\/|(fallbackmsg|elseif|else|ifempty)\b)/.test(textAfter)) indent -= config.indentUnit;
172
+ if (state.tag != "switch" && /^\{(case|default)\b/.test(textAfter)) indent -= config.indentUnit;
173
+ if (/^\{\/switch\b/.test(textAfter)) indent -= config.indentUnit;
174
+ }
175
+ if (indent && state.localMode.indent)
176
+ indent += state.localMode.indent(state.localState, textAfter);
177
+ return indent;
178
+ },
179
+
180
+ innerMode: function(state) {
181
+ if (state.soyState.length && last(state.soyState) != "literal") return null;
182
+ else return {state: state.localState, mode: state.localMode};
183
+ },
184
+
185
+ electricInput: /^\s*\{(\/|\/template|\/deltemplate|\/switch|fallbackmsg|elseif|else|case|default|ifempty|\/literal\})$/,
186
+ lineComment: "//",
187
+ blockCommentStart: "/*",
188
+ blockCommentEnd: "*/",
189
+ blockCommentContinue: " * ",
190
+ fold: "indent"
191
+ };
192
+ }, "htmlmixed");
193
+
194
+ CodeMirror.registerHelper("hintWords", "soy", indentingTags.concat(
195
+ ["delpackage", "namespace", "alias", "print", "css", "debugger"]));
196
+
197
+ CodeMirror.defineMIME("text/x-soy", "soy");
198
+ });