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,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");