codemirror-rails 5.6 → 5.7

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 (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;