codemirror-rails 5.6 → 5.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +30 -17
  4. data/vendor/assets/javascripts/codemirror/addons/display/placeholder.js +3 -1
  5. data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +10 -0
  6. data/vendor/assets/javascripts/codemirror/addons/lint/lint.js +21 -3
  7. data/vendor/assets/javascripts/codemirror/addons/search/search.js +29 -14
  8. data/vendor/assets/javascripts/codemirror/keymaps/sublime.js +11 -3
  9. data/vendor/assets/javascripts/codemirror/modes/clike.js +15 -0
  10. data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +14 -17
  11. data/vendor/assets/javascripts/codemirror/modes/css.js +66 -15
  12. data/vendor/assets/javascripts/codemirror/modes/elm.js +1 -1
  13. data/vendor/assets/javascripts/codemirror/modes/gfm.js +23 -17
  14. data/vendor/assets/javascripts/codemirror/modes/haxe.js +68 -80
  15. data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +125 -96
  16. data/vendor/assets/javascripts/codemirror/modes/javascript.js +14 -5
  17. data/vendor/assets/javascripts/codemirror/modes/markdown.js +40 -29
  18. data/vendor/assets/javascripts/codemirror/modes/mscgen.js +169 -0
  19. data/vendor/assets/javascripts/codemirror/modes/oz.js +252 -0
  20. data/vendor/assets/javascripts/codemirror/modes/php.js +6 -3
  21. data/vendor/assets/javascripts/codemirror/modes/ruby.js +1 -1
  22. data/vendor/assets/javascripts/codemirror/modes/vhdl.js +1 -1
  23. data/vendor/assets/javascripts/codemirror/modes/vue.js +69 -0
  24. data/vendor/assets/stylesheets/codemirror/themes/icecoder.css +1 -0
  25. metadata +6 -3
@@ -9,113 +9,142 @@
9
9
  else // Plain browser env
10
10
  mod(CodeMirror);
11
11
  })(function(CodeMirror) {
12
- "use strict";
13
-
14
- CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
15
- var htmlMode = CodeMirror.getMode(config, {name: "xml",
16
- htmlMode: true,
17
- multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
18
- multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag});
19
- var cssMode = CodeMirror.getMode(config, "css");
20
-
21
- var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes;
22
- scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,
23
- mode: CodeMirror.getMode(config, "javascript")});
24
- if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) {
25
- var conf = scriptTypesConf[i];
26
- scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)});
27
- }
28
- scriptTypes.push({matches: /./,
29
- mode: CodeMirror.getMode(config, "text/plain")});
30
-
31
- function html(stream, state) {
32
- var tagName = state.htmlState.tagName;
33
- if (tagName) tagName = tagName.toLowerCase();
34
- var style = htmlMode.token(stream, state.htmlState);
35
- if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") {
36
- // Script block: mode to change to depends on type attribute
37
- var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);
38
- scriptType = scriptType ? scriptType[1] : "";
39
- if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1);
40
- for (var i = 0; i < scriptTypes.length; ++i) {
41
- var tp = scriptTypes[i];
42
- if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) {
43
- if (tp.mode) {
44
- state.token = script;
45
- state.localMode = tp.mode;
46
- state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, ""));
47
- }
48
- break;
49
- }
50
- }
51
- } else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") {
52
- state.token = css;
53
- state.localMode = cssMode;
54
- state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
55
- }
56
- return style;
57
- }
12
+ "use strict";
13
+
14
+ var defaultTags = {
15
+ script: [
16
+ ["lang", /(javascript|babel)/i, "javascript"],
17
+ ["type", /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i, "javascript"],
18
+ ["type", /./, "text/plain"],
19
+ [null, null, "javascript"]
20
+ ],
21
+ style: [
22
+ ["lang", /^css$/i, "css"],
23
+ ["type", /^(text\/)?(x-)?(stylesheet|css)$/i, "css"],
24
+ ["type", /./, "text/plain"],
25
+ [null, null, "css"]
26
+ ]
27
+ };
28
+
58
29
  function maybeBackup(stream, pat, style) {
59
- var cur = stream.current();
60
- var close = cur.search(pat);
61
- if (close > -1) stream.backUp(cur.length - close);
62
- else if (cur.match(/<\/?$/)) {
30
+ var cur = stream.current(), close = cur.search(pat);
31
+ if (close > -1) {
32
+ stream.backUp(cur.length - close);
33
+ } else if (cur.match(/<\/?$/)) {
63
34
  stream.backUp(cur.length);
64
35
  if (!stream.match(pat, false)) stream.match(cur);
65
36
  }
66
37
  return style;
67
38
  }
68
- function script(stream, state) {
69
- if (stream.match(/^<\/\s*script\s*>/i, false)) {
70
- state.token = html;
71
- state.localState = state.localMode = null;
72
- return null;
73
- }
74
- return maybeBackup(stream, /<\/\s*script\s*>/,
75
- state.localMode.token(stream, state.localState));
39
+
40
+ var attrRegexpCache = {};
41
+ function getAttrRegexp(attr) {
42
+ var regexp = attrRegexpCache[attr];
43
+ if (regexp) return regexp;
44
+ return attrRegexpCache[attr] = new RegExp("\\s+" + attr + "\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*");
45
+ }
46
+
47
+ function getAttrValue(stream, attr) {
48
+ var pos = stream.pos, match;
49
+ while (pos >= 0 && stream.string.charAt(pos) !== "<") pos--;
50
+ if (pos < 0) return pos;
51
+ if (match = stream.string.slice(pos, stream.pos).match(getAttrRegexp(attr)))
52
+ return match[2];
53
+ return "";
54
+ }
55
+
56
+ function getTagRegexp(tagName, anchored) {
57
+ return new RegExp((anchored ? "^" : "") + "<\/\s*" + tagName + "\s*>", "i");
76
58
  }
77
- function css(stream, state) {
78
- if (stream.match(/^<\/\s*style\s*>/i, false)) {
79
- state.token = html;
80
- state.localState = state.localMode = null;
81
- return null;
59
+
60
+ function addTags(from, to) {
61
+ for (var tag in from) {
62
+ var dest = to[tag] || (to[tag] = []);
63
+ var source = from[tag];
64
+ for (var i = source.length - 1; i >= 0; i--)
65
+ dest.unshift(source[i])
82
66
  }
83
- return maybeBackup(stream, /<\/\s*style\s*>/,
84
- cssMode.token(stream, state.localState));
85
67
  }
86
68
 
87
- return {
88
- startState: function() {
89
- var state = htmlMode.startState();
90
- return {token: html, localMode: null, localState: null, htmlState: state};
91
- },
92
-
93
- copyState: function(state) {
94
- if (state.localState)
95
- var local = CodeMirror.copyState(state.localMode, state.localState);
96
- return {token: state.token, localMode: state.localMode, localState: local,
97
- htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
98
- },
99
-
100
- token: function(stream, state) {
101
- return state.token(stream, state);
102
- },
103
-
104
- indent: function(state, textAfter) {
105
- if (!state.localMode || /^\s*<\//.test(textAfter))
106
- return htmlMode.indent(state.htmlState, textAfter);
107
- else if (state.localMode.indent)
108
- return state.localMode.indent(state.localState, textAfter);
109
- else
110
- return CodeMirror.Pass;
111
- },
112
-
113
- innerMode: function(state) {
114
- return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
69
+ function findMatchingMode(tagInfo, stream) {
70
+ for (var i = 0; i < tagInfo.length; i++) {
71
+ var spec = tagInfo[i];
72
+ if (!spec[0] || spec[1].test(getAttrValue(stream, spec[0]))) return spec[2];
115
73
  }
116
- };
117
- }, "xml", "javascript", "css");
74
+ }
75
+
76
+ CodeMirror.defineMode("htmlmixed", function (config, parserConfig) {
77
+ var htmlMode = CodeMirror.getMode(config, {
78
+ name: "xml",
79
+ htmlMode: true,
80
+ multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
81
+ multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag
82
+ });
83
+
84
+ var tags = {};
85
+ var configTags = parserConfig && parserConfig.tags, configScript = parserConfig && parserConfig.scriptTypes;
86
+ addTags(defaultTags, tags);
87
+ if (configTags) addTags(configTags, tags);
88
+ if (configScript) for (var i = configScript.length - 1; i >= 0; i--)
89
+ tags.script.unshift(["type", configScript[i].matches, configScript[i].mode])
90
+
91
+ function html(stream, state) {
92
+ var tagName = state.htmlState.tagName;
93
+ var tagInfo = tagName && tags[tagName.toLowerCase()];
94
+
95
+ var style = htmlMode.token(stream, state.htmlState), modeSpec;
96
+
97
+ if (tagInfo && /\btag\b/.test(style) && stream.current() === ">" &&
98
+ (modeSpec = findMatchingMode(tagInfo, stream))) {
99
+ var mode = CodeMirror.getMode(config, modeSpec);
100
+ var endTagA = getTagRegexp(tagName, true), endTag = getTagRegexp(tagName, false);
101
+ state.token = function (stream, state) {
102
+ if (stream.match(endTagA, false)) {
103
+ state.token = html;
104
+ state.localState = state.localMode = null;
105
+ return null;
106
+ }
107
+ return maybeBackup(stream, endTag, state.localMode.token(stream, state.localState));
108
+ };
109
+ state.localMode = mode;
110
+ state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, ""));
111
+ }
112
+ return style;
113
+ };
114
+
115
+ return {
116
+ startState: function () {
117
+ var state = htmlMode.startState();
118
+ return {token: html, localMode: null, localState: null, htmlState: state};
119
+ },
120
+
121
+ copyState: function (state) {
122
+ var local;
123
+ if (state.localState) {
124
+ local = CodeMirror.copyState(state.localMode, state.localState);
125
+ }
126
+ return {token: state.token, localMode: state.localMode, localState: local,
127
+ htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
128
+ },
129
+
130
+ token: function (stream, state) {
131
+ return state.token(stream, state);
132
+ },
118
133
 
119
- CodeMirror.defineMIME("text/html", "htmlmixed");
134
+ indent: function (state, textAfter) {
135
+ if (!state.localMode || /^\s*<\//.test(textAfter))
136
+ return htmlMode.indent(state.htmlState, textAfter);
137
+ else if (state.localMode.indent)
138
+ return state.localMode.indent(state.localState, textAfter);
139
+ else
140
+ return CodeMirror.Pass;
141
+ },
142
+
143
+ innerMode: function (state) {
144
+ return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
145
+ }
146
+ };
147
+ }, "xml", "javascript", "css");
120
148
 
149
+ CodeMirror.defineMIME("text/html", "htmlmixed");
121
150
  });
@@ -32,12 +32,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
32
32
  "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
33
33
  "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C,
34
34
  "var": kw("var"), "const": kw("var"), "let": kw("var"),
35
- "function": kw("function"), "catch": kw("catch"),
35
+ "async": kw("async"), "function": kw("function"), "catch": kw("catch"),
36
36
  "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
37
37
  "in": operator, "typeof": operator, "instanceof": operator,
38
38
  "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
39
39
  "this": kw("this"), "class": kw("class"), "super": kw("atom"),
40
- "yield": C, "export": kw("export"), "import": kw("import"), "extends": C
40
+ "await": C, "yield": C, "export": kw("export"), "import": kw("import"), "extends": C
41
41
  };
42
42
 
43
43
  // Extend the 'normal' keywords with the TypeScript language extensions
@@ -105,6 +105,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
105
105
  } else if (ch == "0" && stream.eat(/x/i)) {
106
106
  stream.eatWhile(/[\da-f]/i);
107
107
  return ret("number", "number");
108
+ } else if (ch == "0" && stream.eat(/o/i)) {
109
+ stream.eatWhile(/[0-7]/i);
110
+ return ret("number", "number");
111
+ } else if (ch == "0" && stream.eat(/b/i)) {
112
+ stream.eatWhile(/[01]/i);
113
+ return ret("number", "number");
108
114
  } else if (/\d/.test(ch)) {
109
115
  stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
110
116
  return ret("number", "number");
@@ -348,8 +354,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
348
354
  if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
349
355
  statement, poplex, popcontext);
350
356
  if (type == "class") return cont(pushlex("form"), className, poplex);
351
- if (type == "export") return cont(pushlex("form"), afterExport, poplex);
352
- if (type == "import") return cont(pushlex("form"), afterImport, poplex);
357
+ if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
358
+ if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
353
359
  return pass(pushlex("stat"), expression, expect(";"), poplex);
354
360
  }
355
361
  function expression(type) {
@@ -367,6 +373,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
367
373
 
368
374
  var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
369
375
  if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
376
+ if (type == "async") return cont(expression);
370
377
  if (type == "function") return cont(functiondef, maybeop);
371
378
  if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
372
379
  if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
@@ -432,7 +439,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
432
439
  if (type == "variable") {cx.marked = "property"; return cont();}
433
440
  }
434
441
  function objprop(type, value) {
435
- if (type == "variable" || cx.style == "keyword") {
442
+ if (type == "async") {
443
+ return cont(objprop);
444
+ } else if (type == "variable" || cx.style == "keyword") {
436
445
  cx.marked = "property";
437
446
  if (value == "get" || value == "set") return cont(getterSetter);
438
447
  return cont(afterprop);
@@ -39,8 +39,10 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
39
39
  if (modeCfg.underscoresBreakWords === undefined)
40
40
  modeCfg.underscoresBreakWords = true;
41
41
 
42
- // Turn on fenced code blocks? ("```" to start/end)
43
- if (modeCfg.fencedCodeBlocks === undefined) modeCfg.fencedCodeBlocks = false;
42
+ // Use `fencedCodeBlocks` to configure fenced code blocks. false to
43
+ // disable, string to specify a precise regexp that the fence should
44
+ // match, and true to allow three or more backticks or tildes (as
45
+ // per CommonMark).
44
46
 
45
47
  // Turn on task lists? ("- [ ] " and "- [x] ")
46
48
  if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;
@@ -72,9 +74,11 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
72
74
  , ulRE = /^[*\-+]\s+/
73
75
  , olRE = /^[0-9]+([.)])\s+/
74
76
  , taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE
75
- , atxHeaderRE = /^(#+)(?: |$)/
77
+ , atxHeaderRE = modeCfg.allowAtxHeaderWithoutSpace ? /^(#+)/ : /^(#+)(?: |$)/
76
78
  , setextHeaderRE = /^ *(?:\={1,}|-{1,})\s*$/
77
- , textRE = /^[^#!\[\]*_\\<>` "'(~]+/;
79
+ , textRE = /^[^#!\[\]*_\\<>` "'(~]+/
80
+ , fencedCodeRE = new RegExp("^(" + (modeCfg.fencedCodeBlocks === true ? "~~~+|```+" : modeCfg.fencedCodeBlocks) +
81
+ ")[ \\t]*([\\w+#]*)");
78
82
 
79
83
  function switchInline(stream, state, f) {
80
84
  state.f = state.inline = f;
@@ -86,6 +90,9 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
86
90
  return f(stream, state);
87
91
  }
88
92
 
93
+ function lineIsEmpty(line) {
94
+ return !line || !/\S/.test(line.string)
95
+ }
89
96
 
90
97
  // Blocks
91
98
 
@@ -110,7 +117,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
110
117
  state.trailingSpace = 0;
111
118
  state.trailingSpaceNewLine = false;
112
119
  // Mark this line as blank
113
- state.thisLineHasContent = false;
120
+ state.prevLine = state.thisLine
121
+ state.thisLine = null
114
122
  return null;
115
123
  }
116
124
 
@@ -141,7 +149,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
141
149
  var match = null;
142
150
  if (state.indentationDiff >= 4) {
143
151
  stream.skipToEnd();
144
- if (prevLineIsIndentedCode || !state.prevLineHasContent) {
152
+ if (prevLineIsIndentedCode || lineIsEmpty(state.prevLine)) {
145
153
  state.indentation -= 4;
146
154
  state.indentedCode = true;
147
155
  return code;
@@ -155,7 +163,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
155
163
  if (modeCfg.highlightFormatting) state.formatting = "header";
156
164
  state.f = state.inline;
157
165
  return getType(state);
158
- } else if (state.prevLineHasContent && !state.quote && !prevLineIsList && !prevLineIsIndentedCode && (match = stream.match(setextHeaderRE))) {
166
+ } else if (!lineIsEmpty(state.prevLine) && !state.quote && !prevLineIsList &&
167
+ !prevLineIsIndentedCode && (match = stream.match(setextHeaderRE))) {
159
168
  state.header = match[0].charAt(0) == '=' ? 1 : 2;
160
169
  if (modeCfg.highlightFormatting) state.formatting = "header";
161
170
  state.f = state.inline;
@@ -170,7 +179,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
170
179
  } else if (stream.match(hrRE, true)) {
171
180
  state.hr = true;
172
181
  return hr;
173
- } else if ((!state.prevLineHasContent || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) {
182
+ } else if ((lineIsEmpty(state.prevLine) || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) {
174
183
  var listType = null;
175
184
  if (stream.match(ulRE, true)) {
176
185
  listType = 'ul';
@@ -178,7 +187,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
178
187
  stream.match(olRE, true);
179
188
  listType = 'ol';
180
189
  }
181
- state.indentation += 4;
190
+ state.indentation = stream.column() + stream.current().length;
182
191
  state.list = true;
183
192
  state.listDepth++;
184
193
  if (modeCfg.taskLists && stream.match(taskListRE, false)) {
@@ -187,9 +196,10 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
187
196
  state.f = state.inline;
188
197
  if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
189
198
  return getType(state);
190
- } else if (modeCfg.fencedCodeBlocks && stream.match(/^```[ \t]*([\w+#]*)/, true)) {
199
+ } else if (modeCfg.fencedCodeBlocks && (match = stream.match(fencedCodeRE, true))) {
200
+ state.fencedChars = match[1]
191
201
  // try switching mode
192
- state.localMode = getMode(RegExp.$1);
202
+ state.localMode = getMode(match[2]);
193
203
  if (state.localMode) state.localState = state.localMode.startState();
194
204
  state.f = state.block = local;
195
205
  if (modeCfg.highlightFormatting) state.formatting = "code-block";
@@ -213,7 +223,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
213
223
  }
214
224
 
215
225
  function local(stream, state) {
216
- if (stream.sol() && stream.match("```", false)) {
226
+ if (stream.sol() && state.fencedChars && stream.match(state.fencedChars, false)) {
217
227
  state.localMode = state.localState = null;
218
228
  state.f = state.block = leavingLocal;
219
229
  return null;
@@ -226,9 +236,10 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
226
236
  }
227
237
 
228
238
  function leavingLocal(stream, state) {
229
- stream.match("```");
239
+ stream.match(state.fencedChars);
230
240
  state.block = blockNormal;
231
241
  state.f = inlineNormal;
242
+ state.fencedChars = null;
232
243
  if (modeCfg.highlightFormatting) state.formatting = "code-block";
233
244
  state.code = true;
234
245
  var returnType = getType(state);
@@ -656,8 +667,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
656
667
  return {
657
668
  f: blockNormal,
658
669
 
659
- prevLineHasContent: false,
660
- thisLineHasContent: false,
670
+ prevLine: null,
671
+ thisLine: null,
661
672
 
662
673
  block: blockNormal,
663
674
  htmlState: null,
@@ -680,7 +691,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
680
691
  quote: 0,
681
692
  trailingSpace: 0,
682
693
  trailingSpaceNewLine: false,
683
- strikethrough: false
694
+ strikethrough: false,
695
+ fencedChars: null
684
696
  };
685
697
  },
686
698
 
@@ -688,8 +700,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
688
700
  return {
689
701
  f: s.f,
690
702
 
691
- prevLineHasContent: s.prevLineHasContent,
692
- thisLineHasContent: s.thisLineHasContent,
703
+ prevLine: s.prevLine,
704
+ thisLine: s.this,
693
705
 
694
706
  block: s.block,
695
707
  htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),
@@ -702,6 +714,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
702
714
  text: s.text,
703
715
  formatting: false,
704
716
  linkTitle: s.linkTitle,
717
+ code: s.code,
705
718
  em: s.em,
706
719
  strong: s.strong,
707
720
  strikethrough: s.strikethrough,
@@ -714,7 +727,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
714
727
  indentedCode: s.indentedCode,
715
728
  trailingSpace: s.trailingSpace,
716
729
  trailingSpaceNewLine: s.trailingSpaceNewLine,
717
- md_inside: s.md_inside
730
+ md_inside: s.md_inside,
731
+ fencedChars: s.fencedChars
718
732
  };
719
733
  },
720
734
 
@@ -723,28 +737,25 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
723
737
  // Reset state.formatting
724
738
  state.formatting = false;
725
739
 
726
- if (stream.sol()) {
727
- var forceBlankLine = !!state.header || state.hr;
740
+ if (stream != state.thisLine) {
741
+ var forceBlankLine = state.header || state.hr;
728
742
 
729
743
  // Reset state.header and state.hr
730
744
  state.header = 0;
731
745
  state.hr = false;
732
746
 
733
747
  if (stream.match(/^\s*$/, true) || forceBlankLine) {
734
- state.prevLineHasContent = false;
735
748
  blankLine(state);
736
- return forceBlankLine ? this.token(stream, state) : null;
737
- } else {
738
- state.prevLineHasContent = state.thisLineHasContent;
739
- state.thisLineHasContent = true;
749
+ if (!forceBlankLine) return null
750
+ state.prevLine = null
740
751
  }
741
752
 
753
+ state.prevLine = state.thisLine
754
+ state.thisLine = stream
755
+
742
756
  // Reset state.taskList
743
757
  state.taskList = false;
744
758
 
745
- // Reset state.code
746
- state.code = false;
747
-
748
759
  // Reset state.trailingSpace
749
760
  state.trailingSpace = 0;
750
761
  state.trailingSpaceNewLine = false;