@@ -89,7 +89,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
8989 , atxHeaderRE = modeCfg . allowAtxHeaderWithoutSpace ? / ^ ( # + ) / : / ^ ( # + ) (?: | $ ) /
9090 , setextHeaderRE = / ^ * (?: \= { 1 , } | - { 1 , } ) \s * $ /
9191 , textRE = / ^ [ ^ # ! \[ \] * _ \\ < > ` " ' ( ~ : ] + /
92- , fencedCodeRE = / ^ ( ~ ~ ~ + | ` ` ` + ) [ \t ] * ( [ \w + # - ] * ) /
92+ , fencedCodeRE = / ^ ( ~ ~ ~ + | ` ` ` + ) [ \t ] * ( [ \w + # - ] * ) [ ^ \n ` ] * $ /
9393 , linkDefRE = / ^ \s * \[ [ ^ \] ] + ?\] : \s * \S + ( \s * \S * \s * ) ? $ / // naive link-definition
9494 , punctuation = / [ ! \" # $ % & \' ( ) * + , \- \. \/ : ; < = > ? @ \[ \\ \] ^ _ ` { | } ~ — ] /
9595 , expandedTab = " " // CommonMark specifies tab as 4 spaces
@@ -133,13 +133,13 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
133133 state . trailingSpaceNewLine = false ;
134134 // Mark this line as blank
135135 state . prevLine = state . thisLine
136- state . thisLine = null
136+ state . thisLine = { stream : null }
137137 return null ;
138138 }
139139
140140 function blockNormal ( stream , state ) {
141141 var firstTokenOnLine = stream . column ( ) === state . indentation ;
142- var prevLineLineIsEmpty = lineIsEmpty ( state . prevLine ) ;
142+ var prevLineLineIsEmpty = lineIsEmpty ( state . prevLine . stream ) ;
143143 var prevLineIsIndentedCode = state . indentedCode ;
144144 var prevLineIsHr = state . hr ;
145145 var prevLineIsList = state . list !== false ;
@@ -176,7 +176,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
176176 state . indentation <= maxNonCodeIndentation && stream . match ( hrRE ) ;
177177
178178 var match = null ;
179- if ( state . indentationDiff >= 4 && ( prevLineIsIndentedCode || prevLineLineIsEmpty ) ) {
179+ if ( state . indentationDiff >= 4 && ( prevLineIsIndentedCode || state . prevLine . fencedCodeEnd ||
180+ state . prevLine . header || prevLineLineIsEmpty ) ) {
180181 stream . skipToEnd ( ) ;
181182 state . indentedCode = true ;
182183 return tokenTypes . code ;
@@ -185,6 +186,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
185186 } else if ( firstTokenOnLine && state . indentation <= maxNonCodeIndentation && ( match = stream . match ( atxHeaderRE ) ) && match [ 1 ] . length <= 6 ) {
186187 state . quote = 0 ;
187188 state . header = match [ 1 ] . length ;
189+ state . thisLine . header = true ;
188190 if ( modeCfg . highlightFormatting ) state . formatting = "header" ;
189191 state . f = state . inline ;
190192 return getType ( state ) ;
@@ -211,7 +213,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
211213 return getType ( state ) ;
212214 } else if ( firstTokenOnLine && state . indentation <= maxNonCodeIndentation && ( match = stream . match ( fencedCodeRE , true ) ) ) {
213215 state . quote = 0 ;
214- state . fencedChars = match [ 1 ]
216+ state . fencedEndRE = new RegExp ( match [ 1 ] + "+ *$" ) ;
215217 // try switching mode
216218 state . localMode = modeCfg . fencedCodeBlockHighlighting && getMode ( match [ 2 ] ) ;
217219 if ( state . localMode ) state . localState = CodeMirror . startState ( state . localMode ) ;
@@ -240,6 +242,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
240242 stream . skipToEnd ( ) ;
241243 if ( modeCfg . highlightFormatting ) state . formatting = "header" ;
242244 }
245+ state . thisLine . header = true ;
243246 state . f = state . inline ;
244247 return getType ( state ) ;
245248 } else if ( isHr ) {
@@ -269,20 +272,21 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
269272 }
270273
271274 function local ( stream , state ) {
272- var hasExitedList = state . indentation < state . listStack [ state . listStack . length - 1 ] ;
273- if ( state . fencedChars && ( hasExitedList || stream . match ( state . fencedChars ) ) ) {
275+ var currListInd = state . listStack [ state . listStack . length - 1 ] || 0 ;
276+ var hasExitedList = state . indentation < currListInd ;
277+ var maxFencedEndInd = currListInd + 3 ;
278+ if ( state . fencedEndRE && state . indentation <= maxFencedEndInd && ( hasExitedList || stream . match ( state . fencedEndRE ) ) ) {
274279 if ( modeCfg . highlightFormatting ) state . formatting = "code-block" ;
275280 var returnType ;
276281 if ( ! hasExitedList ) returnType = getType ( state )
277282 state . localMode = state . localState = null ;
278283 state . block = blockNormal ;
279284 state . f = inlineNormal ;
280- state . fencedChars = null ;
285+ state . fencedEndRE = null ;
281286 state . code = 0
287+ state . thisLine . fencedCodeEnd = true ;
282288 if ( hasExitedList ) return switchBlock ( stream , state , state . block ) ;
283289 return returnType ;
284- } else if ( state . fencedChars && stream . skipTo ( state . fencedChars ) ) {
285- return "comment"
286290 } else if ( state . localMode ) {
287291 return state . localMode . token ( stream , state . localState ) ;
288292 } else {
@@ -716,8 +720,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
716720 return {
717721 f : blockNormal ,
718722
719- prevLine : null ,
720- thisLine : null ,
723+ prevLine : { stream : null } ,
724+ thisLine : { stream : null } ,
721725
722726 block : blockNormal ,
723727 htmlState : null ,
@@ -744,7 +748,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
744748 trailingSpaceNewLine : false ,
745749 strikethrough : false ,
746750 emoji : false ,
747- fencedChars : null
751+ fencedEndRE : null
748752 } ;
749753 } ,
750754
@@ -783,7 +787,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
783787 trailingSpace : s . trailingSpace ,
784788 trailingSpaceNewLine : s . trailingSpaceNewLine ,
785789 md_inside : s . md_inside ,
786- fencedChars : s . fencedChars
790+ fencedEndRE : s . fencedEndRE
787791 } ;
788792 } ,
789793
@@ -792,8 +796,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
792796 // Reset state.formatting
793797 state . formatting = false ;
794798
795- if ( stream != state . thisLine ) {
796799 // Reset state.header
800+ if ( stream != state . thisLine . stream ) {
797801 state . header = 0 ;
798802
799803 if ( stream . match ( / ^ \s * $ / , true ) ) {
@@ -802,7 +806,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
802806 }
803807
804808 state . prevLine = state . thisLine
805- state . thisLine = stream
809+ state . thisLine = { stream : stream }
806810
807811 // Reset state.taskList
808812 state . taskList = false ;
0 commit comments