codemirror-rails 3.20 → 3.21

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 (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,7 +1,17 @@
1
1
  CodeMirror.defineMode("jinja2", function() {
2
- var keywords = ["block", "endblock", "for", "endfor", "in", "true", "false",
3
- "loop", "none", "self", "super", "if", "as", "not", "and",
4
- "else", "import", "with", "without", "context"];
2
+ var keywords = ["and", "as", "block", "endblock", "by", "cycle", "debug", "else", "elif",
3
+ "extends", "filter", "endfilter", "firstof", "for",
4
+ "endfor", "if", "endif", "ifchanged", "endifchanged",
5
+ "ifequal", "endifequal", "ifnotequal",
6
+ "endifnotequal", "in", "include", "load", "not", "now", "or",
7
+ "parsed", "regroup", "reversed", "spaceless",
8
+ "endspaceless", "ssi", "templatetag", "openblock",
9
+ "closeblock", "openvariable", "closevariable",
10
+ "openbrace", "closebrace", "opencomment",
11
+ "closecomment", "widthratio", "url", "with", "endwith",
12
+ "get_current_language", "trans", "noop", "blocktrans",
13
+ "endblocktrans", "get_available_languages",
14
+ "get_current_language_bidi", "plural"];
5
15
  keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b");
6
16
 
7
17
  function tokenBase (stream, state) {
@@ -71,7 +71,7 @@ CodeMirror.defineMode("less", function(config) {
71
71
  if(stream.peek() === " ")stream.eatSpace();
72
72
  if(stream.peek() === ")" || type === ":")return ret("number", "unit");//rgba(0,0,0,.25);
73
73
  else if(stream.current().length >1){
74
- if(state.stack[state.stack.length-1] === "rule" && stream.peek().match(/{|,|\+|\(/) === null)return ret("number", "unit");
74
+ if(state.stack[state.stack.length-1] === "rule" && !stream.match(/^[{,+(]/, false)) return ret("number", "unit");
75
75
  }
76
76
  return ret("tag", "tag");
77
77
  } else if (ch == "#") {
@@ -170,7 +170,7 @@ CodeMirror.defineMode("less", function(config) {
170
170
  } else if(type == "compare" || type == "a" || type == "("){
171
171
  return ret("string", "string");
172
172
  } else if(type == "|" || stream.current() == "-" || type == "["){
173
- if(type == "|" && stream.peek().match(/\]|=|\~/) !== null)return ret("number", stream.current());
173
+ if (type == "|" && stream.match(/^[\]=~]/, false)) return ret("number", stream.current());
174
174
  else if(type == "|" )return ret("tag", "tag");
175
175
  else if(type == "["){
176
176
  stream.eatWhile(/\w\-/);
@@ -201,7 +201,7 @@ CodeMirror.defineMode("less", function(config) {
201
201
 
202
202
  //else if((type === ")" && state.stack[state.stack.length-1] === "rule") || (state.stack[state.stack.length-2] === "{" && state.stack[state.stack.length-1] === "rule" && type === "variable"))return ret(null, stream.current());
203
203
 
204
- else if(/\^|\$/.test(stream.current()) && stream.peek().match(/\~|=/) !== null)return ret("string", "string");//att^=val
204
+ else if (/\^|\$/.test(stream.current()) && stream.match(/^[~=]/, false)) return ret("string", "string");//att^=val
205
205
 
206
206
  else if(type === "unit" && state.stack[state.stack.length-1] === "rule")return ret(null, "unit");
207
207
  else if(type === "unit" && state.stack[state.stack.length-1] === ";")return ret(null, "unit");
@@ -210,12 +210,13 @@ CodeMirror.defineMode("less", function(config) {
210
210
  //else if(type === "unit" && state.stack[state.stack.length-1] === "rule")return ret(null, stream.current());
211
211
 
212
212
  else if((type === ";" || type === "}" || type === ",") && state.stack[state.stack.length-1] === ";")return ret("tag", stream.current());
213
- else if((type === ";" && stream.peek() !== undefined && stream.peek().match(/{|./) === null) || (type === ";" && stream.eatSpace() && stream.peek().match(/{|./) === null))return ret("variable", stream.current());
213
+ else if((type === ";" && stream.peek() !== undefined && !stream.match(/^[{\.]/, false)) ||
214
+ (type === ";" && stream.eatSpace() && !stream.match(/^[{\.]/))) return ret("variable", stream.current());
214
215
  else if((type === "@media" && state.stack[state.stack.length-1] === "@media") || type === "@namespace")return ret("tag", stream.current());
215
216
 
216
217
  else if(type === "{" && state.stack[state.stack.length-1] === ";" && stream.peek() === "{")return ret("tag", "tag");
217
218
  else if((type === "{" || type === ":") && state.stack[state.stack.length-1] === ";")return ret(null, stream.current());
218
- else if((state.stack[state.stack.length-1] === "{" && stream.eatSpace() && stream.peek().match(/.|#/) === null) || type === "select-op" || (state.stack[state.stack.length-1] === "rule" && type === ",") )return ret("tag", "tag");
219
+ else if((state.stack[state.stack.length-1] === "{" && stream.eatSpace() && !stream.match(/^[\.#]/)) || type === "select-op" || (state.stack[state.stack.length-1] === "rule" && type === ",") )return ret("tag", "tag");
219
220
  else if(type === "variable" && state.stack[state.stack.length-1] === "rule")return ret("tag", "tag");
220
221
  else if((stream.eatSpace() && stream.peek() === "{") || stream.eol() || stream.peek() === "{")return ret("tag", "tag");
221
222
  //this one messes up indentation
@@ -227,7 +228,7 @@ CodeMirror.defineMode("less", function(config) {
227
228
  else if(stream.sol())return ret("tag", "tag");
228
229
  else if((stream.eatSpace() && stream.peek() === "#") || stream.peek() === "#")return ret("tag", "tag");
229
230
  else if(state.stack.length === 0)return ret("tag", "tag");
230
- else if(type === ";" && stream.peek() !== undefined && stream.peek().match(/^[.|\#]/g) !== null)return ret("tag", "tag");
231
+ else if(type === ";" && stream.peek() !== undefined && stream.match(/^[\.|#]/g)) return ret("tag", "tag");
231
232
 
232
233
  else if(type === ":"){stream.eatSpace();return ret(null, stream.current());}
233
234
 
@@ -42,6 +42,16 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
42
42
  };
43
43
  }());
44
44
 
45
+ // Should characters that affect highlighting be highlighted separate?
46
+ // Does not include characters that will be output (such as `1.` and `-` for lists)
47
+ if (modeCfg.highlightFormatting === undefined)
48
+ modeCfg.highlightFormatting = false;
49
+
50
+ // Maximum number of nested blockquotes. Set to 0 for infinite nesting.
51
+ // Excess `>` will emit `error` token.
52
+ if (modeCfg.maxBlockquoteDepth === undefined)
53
+ modeCfg.maxBlockquoteDepth = 0;
54
+
45
55
  // Should underscores in words open/close em/strong?
46
56
  if (modeCfg.underscoresBreakWords === undefined)
47
57
  modeCfg.underscoresBreakWords = true;
@@ -56,13 +66,13 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
56
66
 
57
67
  var header = 'header'
58
68
  , code = 'comment'
59
- , quote1 = 'atom'
60
- , quote2 = 'number'
69
+ , quote = 'quote'
61
70
  , list1 = 'variable-2'
62
71
  , list2 = 'variable-3'
63
72
  , list3 = 'keyword'
64
73
  , hr = 'hr'
65
74
  , image = 'tag'
75
+ , formatting = 'formatting'
66
76
  , linkinline = 'link'
67
77
  , linkemail = 'link'
68
78
  , linktext = 'link'
@@ -76,7 +86,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
76
86
  , taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE
77
87
  , atxHeaderRE = /^#+/
78
88
  , setextHeaderRE = /^(?:\={1,}|-{1,})$/
79
- , textRE = /^[^!\[\]*_\\<>` "'(]+/;
89
+ , textRE = /^[^#!\[\]*_\\<>` "'(]+/;
80
90
 
81
91
  function switchInline(stream, state, f) {
82
92
  state.f = state.inline = f;
@@ -114,6 +124,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
114
124
 
115
125
  function blockNormal(stream, state) {
116
126
 
127
+ var sol = stream.sol();
128
+
117
129
  var prevLineIsList = (state.list !== false);
118
130
  if (state.list !== false && state.indentationDiff >= 0) { // Continued list
119
131
  if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block
@@ -137,33 +149,49 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
137
149
  return null;
138
150
  } else if (match = stream.match(atxHeaderRE)) {
139
151
  state.header = match[0].length <= 6 ? match[0].length : 6;
152
+ if (modeCfg.highlightFormatting) state.formatting = "header";
153
+ state.f = state.inline;
154
+ return getType(state);
140
155
  } else if (state.prevLineHasContent && (match = stream.match(setextHeaderRE))) {
141
156
  state.header = match[0].charAt(0) == '=' ? 1 : 2;
157
+ if (modeCfg.highlightFormatting) state.formatting = "header";
158
+ state.f = state.inline;
159
+ return getType(state);
142
160
  } else if (stream.eat('>')) {
143
161
  state.indentation++;
144
- state.quote = 1;
162
+ state.quote = sol ? 1 : state.quote + 1;
163
+ if (modeCfg.highlightFormatting) state.formatting = "quote";
145
164
  stream.eatSpace();
146
- while (stream.eat('>')) {
147
- stream.eatSpace();
148
- state.quote++;
149
- }
165
+ return getType(state);
150
166
  } else if (stream.peek() === '[') {
151
167
  return switchInline(stream, state, footnoteLink);
152
168
  } else if (stream.match(hrRE, true)) {
153
169
  return hr;
154
- } else if ((!state.prevLineHasContent || prevLineIsList) && (stream.match(ulRE, true) || stream.match(olRE, true))) {
170
+ } else if ((!state.prevLineHasContent || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) {
171
+ var listType = null;
172
+ if (stream.match(ulRE, true)) {
173
+ listType = 'ul';
174
+ } else {
175
+ stream.match(olRE, true);
176
+ listType = 'ol';
177
+ }
155
178
  state.indentation += 4;
156
179
  state.list = true;
157
180
  state.listDepth++;
158
181
  if (modeCfg.taskLists && stream.match(taskListRE, false)) {
159
182
  state.taskList = true;
160
183
  }
184
+ state.f = state.inline;
185
+ if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
186
+ return getType(state);
161
187
  } else if (modeCfg.fencedCodeBlocks && stream.match(/^```([\w+#]*)/, true)) {
162
188
  // try switching mode
163
189
  state.localMode = getMode(RegExp.$1);
164
190
  if (state.localMode) state.localState = state.localMode.startState();
165
191
  switchBlock(stream, state, local);
166
- return code;
192
+ if (modeCfg.highlightFormatting) state.formatting = "code-block";
193
+ state.code = true;
194
+ return getType(state);
167
195
  }
168
196
 
169
197
  return switchInline(stream, state, state.inline);
@@ -171,14 +199,11 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
171
199
 
172
200
  function htmlBlock(stream, state) {
173
201
  var style = htmlMode.token(stream, state.htmlState);
174
- if (htmlFound && style === 'tag' && state.htmlState.type !== 'openTag' && !state.htmlState.context) {
175
- state.f = inlineNormal;
176
- state.block = blockNormal;
177
- }
178
- if (state.md_inside && stream.current().indexOf(">")!=-1) {
202
+ if ((htmlFound && !state.htmlState.tagName && !state.htmlState.context) ||
203
+ (state.md_inside && stream.current().indexOf(">") > -1)) {
179
204
  state.f = inlineNormal;
180
205
  state.block = blockNormal;
181
- state.htmlState.context = undefined;
206
+ state.htmlState = null;
182
207
  }
183
208
  return style;
184
209
  }
@@ -188,7 +213,11 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
188
213
  state.localMode = state.localState = null;
189
214
  state.f = inlineNormal;
190
215
  state.block = blockNormal;
191
- return code;
216
+ if (modeCfg.highlightFormatting) state.formatting = "code-block";
217
+ state.code = true;
218
+ var returnType = getType(state);
219
+ state.code = false;
220
+ return returnType;
192
221
  } else if (state.localMode) {
193
222
  return state.localMode.token(stream, state.localState);
194
223
  } else {
@@ -201,8 +230,43 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
201
230
  function getType(state) {
202
231
  var styles = [];
203
232
 
204
- if (state.taskOpen) { return "meta"; }
205
- if (state.taskClosed) { return "property"; }
233
+ if (state.formatting) {
234
+ styles.push(formatting);
235
+
236
+ if (typeof state.formatting === "string") state.formatting = [state.formatting];
237
+
238
+ for (var i = 0; i < state.formatting.length; i++) {
239
+ styles.push(formatting + "-" + state.formatting[i]);
240
+
241
+ if (state.formatting[i] === "header") {
242
+ styles.push(formatting + "-" + state.formatting[i] + state.header);
243
+ }
244
+
245
+ // Add `formatting-quote` and `formatting-quote-#` for blockquotes
246
+ // Add `error` instead if the maximum blockquote nesting depth is passed
247
+ if (state.formatting[i] === "quote") {
248
+ if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
249
+ styles.push(formatting + "-" + state.formatting[i] + "-" + state.quote);
250
+ } else {
251
+ styles.push("error");
252
+ }
253
+ }
254
+ }
255
+ }
256
+
257
+ if (state.taskOpen) {
258
+ styles.push("meta");
259
+ return styles.length ? styles.join(' ') : null;
260
+ }
261
+ if (state.taskClosed) {
262
+ styles.push("property");
263
+ return styles.length ? styles.join(' ') : null;
264
+ }
265
+
266
+ if (state.linkHref) {
267
+ styles.push(linkhref);
268
+ return styles.length ? styles.join(' ') : null;
269
+ }
206
270
 
207
271
  if (state.strong) { styles.push(strong); }
208
272
  if (state.em) { styles.push(em); }
@@ -212,7 +276,18 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
212
276
  if (state.code) { styles.push(code); }
213
277
 
214
278
  if (state.header) { styles.push(header); styles.push(header + state.header); }
215
- if (state.quote) { styles.push(state.quote % 2 ? quote1 : quote2); }
279
+
280
+ if (state.quote) {
281
+ styles.push(quote);
282
+
283
+ // Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth
284
+ if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
285
+ styles.push(quote + "-" + state.quote);
286
+ } else {
287
+ styles.push(quote + "-" + modeCfg.maxBlockquoteDepth);
288
+ }
289
+ }
290
+
216
291
  if (state.list !== false) {
217
292
  var listMod = (state.listDepth - 1) % 3;
218
293
  if (!listMod) {
@@ -254,6 +329,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
254
329
  var taskOpen = stream.match(taskListRE, true)[1] !== "x";
255
330
  if (taskOpen) state.taskOpen = true;
256
331
  else state.taskClosed = true;
332
+ if (modeCfg.highlightFormatting) state.formatting = "task";
257
333
  state.taskList = false;
258
334
  return getType(state);
259
335
  }
@@ -261,13 +337,24 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
261
337
  state.taskOpen = false;
262
338
  state.taskClosed = false;
263
339
 
340
+ if (state.header && stream.match(/^#+$/, true)) {
341
+ if (modeCfg.highlightFormatting) state.formatting = "header";
342
+ return getType(state);
343
+ }
344
+
264
345
  // Get sol() value now, before character is consumed
265
346
  var sol = stream.sol();
266
347
 
267
348
  var ch = stream.next();
268
349
 
350
+ if (state.escape) {
351
+ state.escape = false;
352
+ return getType(state);
353
+ }
354
+
269
355
  if (ch === '\\') {
270
- stream.next();
356
+ if (modeCfg.highlightFormatting) state.formatting = "escape";
357
+ state.escape = true;
271
358
  return getType(state);
272
359
  }
273
360
 
@@ -287,6 +374,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
287
374
 
288
375
  // If this block is changed, it may need to be updated in GFM mode
289
376
  if (ch === '`') {
377
+ var previousFormatting = state.formatting;
378
+ if (modeCfg.highlightFormatting) state.formatting = "code";
290
379
  var t = getType(state);
291
380
  var before = stream.pos;
292
381
  stream.eatWhile('`');
@@ -300,6 +389,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
300
389
  state.code = false;
301
390
  return t;
302
391
  }
392
+ state.formatting = previousFormatting;
303
393
  return getType(state);
304
394
  }
305
395
  } else if (state.code) {
@@ -314,10 +404,12 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
314
404
 
315
405
  if (ch === '[' && stream.match(/.*\](\(| ?\[)/, false)) {
316
406
  state.linkText = true;
407
+ if (modeCfg.highlightFormatting) state.formatting = "link";
317
408
  return getType(state);
318
409
  }
319
410
 
320
411
  if (ch === ']' && state.linkText) {
412
+ if (modeCfg.highlightFormatting) state.formatting = "link";
321
413
  var type = getType(state);
322
414
  state.linkText = false;
323
415
  state.inline = state.f = linkHref;
@@ -325,21 +417,38 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
325
417
  }
326
418
 
327
419
  if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) {
328
- return switchInline(stream, state, inlineElement(linkinline, '>'));
420
+ state.f = state.inline = linkInline;
421
+ if (modeCfg.highlightFormatting) state.formatting = "link";
422
+ var type = getType(state);
423
+ if (type){
424
+ type += " ";
425
+ } else {
426
+ type = "";
427
+ }
428
+ return type + linkinline;
329
429
  }
330
430
 
331
431
  if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
332
- return switchInline(stream, state, inlineElement(linkemail, '>'));
432
+ state.f = state.inline = linkInline;
433
+ if (modeCfg.highlightFormatting) state.formatting = "link";
434
+ var type = getType(state);
435
+ if (type){
436
+ type += " ";
437
+ } else {
438
+ type = "";
439
+ }
440
+ return type + linkemail;
333
441
  }
334
442
 
335
443
  if (ch === '<' && stream.match(/^\w/, false)) {
336
- if (stream.string.indexOf(">")!=-1) {
444
+ if (stream.string.indexOf(">") != -1) {
337
445
  var atts = stream.string.substring(1,stream.string.indexOf(">"));
338
446
  if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) {
339
447
  state.md_inside = true;
340
448
  }
341
449
  }
342
450
  stream.backUp(1);
451
+ state.htmlState = CodeMirror.startState(htmlMode);
343
452
  return switchBlock(stream, state, htmlBlock);
344
453
  }
345
454
 
@@ -360,21 +469,26 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
360
469
  }
361
470
  }
362
471
  }
363
- var t = getType(state);
364
472
  if (ch === '*' || (ch === '_' && !ignoreUnderscore)) {
365
473
  if (sol && stream.peek() === ' ') {
366
474
  // Do nothing, surrounded by newline and space
367
475
  } else if (state.strong === ch && stream.eat(ch)) { // Remove STRONG
476
+ if (modeCfg.highlightFormatting) state.formatting = "strong";
477
+ var t = getType(state);
368
478
  state.strong = false;
369
479
  return t;
370
480
  } else if (!state.strong && stream.eat(ch)) { // Add STRONG
371
481
  state.strong = ch;
482
+ if (modeCfg.highlightFormatting) state.formatting = "strong";
372
483
  return getType(state);
373
484
  } else if (state.em === ch) { // Remove EM
485
+ if (modeCfg.highlightFormatting) state.formatting = "em";
486
+ var t = getType(state);
374
487
  state.em = false;
375
488
  return t;
376
489
  } else if (!state.em) { // Add EM
377
490
  state.em = ch;
491
+ if (modeCfg.highlightFormatting) state.formatting = "em";
378
492
  return getType(state);
379
493
  }
380
494
  } else if (ch === ' ') {
@@ -398,6 +512,26 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
398
512
  return getType(state);
399
513
  }
400
514
 
515
+ function linkInline(stream, state) {
516
+ var ch = stream.next();
517
+
518
+ if (ch === ">") {
519
+ state.f = state.inline = inlineNormal;
520
+ if (modeCfg.highlightFormatting) state.formatting = "link";
521
+ var type = getType(state);
522
+ if (type){
523
+ type += " ";
524
+ } else {
525
+ type = "";
526
+ }
527
+ return type + linkinline;
528
+ }
529
+
530
+ stream.match(/^[^>]+/, true);
531
+
532
+ return linkinline;
533
+ }
534
+
401
535
  function linkHref(stream, state) {
402
536
  // Check if space, and return NULL if so (to avoid marking the space)
403
537
  if(stream.eatSpace()){
@@ -405,19 +539,60 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
405
539
  }
406
540
  var ch = stream.next();
407
541
  if (ch === '(' || ch === '[') {
408
- return switchInline(stream, state, inlineElement(linkhref, ch === '(' ? ')' : ']'));
542
+ state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]");
543
+ if (modeCfg.highlightFormatting) state.formatting = "link-string";
544
+ state.linkHref = true;
545
+ return getType(state);
409
546
  }
410
547
  return 'error';
411
548
  }
412
549
 
550
+ function getLinkHrefInside(endChar) {
551
+ return function(stream, state) {
552
+ var ch = stream.next();
553
+
554
+ if (ch === endChar) {
555
+ state.f = state.inline = inlineNormal;
556
+ if (modeCfg.highlightFormatting) state.formatting = "link-string";
557
+ var returnState = getType(state);
558
+ state.linkHref = false;
559
+ return returnState;
560
+ }
561
+
562
+ if (stream.match(inlineRE(endChar), true)) {
563
+ stream.backUp(1);
564
+ }
565
+
566
+ state.linkHref = true;
567
+ return getType(state);
568
+ };
569
+ }
570
+
413
571
  function footnoteLink(stream, state) {
414
- if (stream.match(/^[^\]]*\]:/, true)) {
415
- state.f = footnoteUrl;
416
- return linktext;
572
+ if (stream.match(/^[^\]]*\]:/, false)) {
573
+ state.f = footnoteLinkInside;
574
+ stream.next(); // Consume [
575
+ if (modeCfg.highlightFormatting) state.formatting = "link";
576
+ state.linkText = true;
577
+ return getType(state);
417
578
  }
418
579
  return switchInline(stream, state, inlineNormal);
419
580
  }
420
581
 
582
+ function footnoteLinkInside(stream, state) {
583
+ if (stream.match(/^\]:/, true)) {
584
+ state.f = state.inline = footnoteUrl;
585
+ if (modeCfg.highlightFormatting) state.formatting = "link";
586
+ var returnType = getType(state);
587
+ state.linkText = false;
588
+ return returnType;
589
+ }
590
+
591
+ stream.match(/^[^\]]+/, true);
592
+
593
+ return linktext;
594
+ }
595
+
421
596
  function footnoteUrl(stream, state) {
422
597
  // Check if space, and return NULL if so (to avoid marking the space)
423
598
  if(stream.eatSpace()){
@@ -447,16 +622,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
447
622
  return savedInlineRE[endChar];
448
623
  }
449
624
 
450
- function inlineElement(type, endChar, next) {
451
- next = next || inlineNormal;
452
- return function(stream, state) {
453
- stream.match(inlineRE(endChar));
454
- state.inline = state.f = next;
455
- return type;
456
- };
457
- }
458
-
459
- return {
625
+ var mode = {
460
626
  startState: function() {
461
627
  return {
462
628
  f: blockNormal,
@@ -465,13 +631,16 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
465
631
  thisLineHasContent: false,
466
632
 
467
633
  block: blockNormal,
468
- htmlState: CodeMirror.startState(htmlMode),
634
+ htmlState: null,
469
635
  indentation: 0,
470
636
 
471
637
  inline: inlineNormal,
472
638
  text: handleText,
473
639
 
640
+ escape: false,
641
+ formatting: false,
474
642
  linkText: false,
643
+ linkHref: false,
475
644
  linkTitle: false,
476
645
  em: false,
477
646
  strong: false,
@@ -493,7 +662,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
493
662
  thisLineHasContent: s.thisLineHasContent,
494
663
 
495
664
  block: s.block,
496
- htmlState: CodeMirror.copyState(htmlMode, s.htmlState),
665
+ htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),
497
666
  indentation: s.indentation,
498
667
 
499
668
  localMode: s.localMode,
@@ -501,6 +670,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
501
670
 
502
671
  inline: s.inline,
503
672
  text: s.text,
673
+ escape: false,
674
+ formatting: false,
504
675
  linkTitle: s.linkTitle,
505
676
  em: s.em,
506
677
  strong: s.strong,
@@ -516,8 +687,17 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
516
687
  },
517
688
 
518
689
  token: function(stream, state) {
690
+
691
+ // Reset state.formatting
692
+ state.formatting = false;
693
+
519
694
  if (stream.sol()) {
520
- if (stream.match(/^\s*$/, true)) {
695
+ var forceBlankLine = stream.match(/^\s*$/, true) || state.header;
696
+
697
+ // Reset state.header
698
+ state.header = 0;
699
+
700
+ if (forceBlankLine) {
521
701
  state.prevLineHasContent = false;
522
702
  return blankLine(state);
523
703
  } else {
@@ -525,8 +705,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
525
705
  state.thisLineHasContent = true;
526
706
  }
527
707
 
528
- // Reset state.header
529
- state.header = 0;
708
+ // Reset state.escape
709
+ state.escape = false;
530
710
 
531
711
  // Reset state.taskList
532
712
  state.taskList = false;
@@ -550,11 +730,17 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
550
730
  return state.f(stream, state);
551
731
  },
552
732
 
733
+ innerMode: function(state) {
734
+ if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode};
735
+ if (state.localState) return {state: state.localState, mode: state.localMode};
736
+ return {state: state, mode: mode};
737
+ },
738
+
553
739
  blankLine: blankLine,
554
740
 
555
741
  getType: getType
556
742
  };
557
-
743
+ return mode;
558
744
  }, "xml");
559
745
 
560
746
  CodeMirror.defineMIME("text/x-markdown", "markdown");