@@ -35,10 +35,6 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
3535 if ( modeCfg . maxBlockquoteDepth === undefined )
3636 modeCfg . maxBlockquoteDepth = 0 ;
3737
38- // Should underscores in words open/close em/strong?
39- if ( modeCfg . underscoresBreakWords === undefined )
40- modeCfg . underscoresBreakWords = true ;
41-
4238 // Use `fencedCodeBlocks` to configure fenced code blocks. false to
4339 // disable, string to specify a precise regexp that the fence should
4440 // match, and true to allow three or more backticks or tildes (as
@@ -91,6 +87,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
9187 , textRE = / ^ [ ^ # ! \[ \] * _ \\ < > \$ ` " ' ( ~ ] + /
9288 , fencedCodeRE = new RegExp ( "^(" + ( modeCfg . fencedCodeBlocks === true ? "~~~+|```+" : modeCfg . fencedCodeBlocks ) +
9389 ")[ \\t]*([\\w+#\-]*)" )
90+ , punctuation = / [ ! \" # $ % & \' ( ) * + , \- \. \/ : ; < = > ? @ \[ \\ \] ^ _ ` { | } ~ — ] /
9491 , fencedMathRE = new RegExp ( "^(\$\$)[ \\t]*([\\w+#\-]*)" ) ;
9592
9693 function switchInline ( stream , state , f ) {
@@ -136,7 +133,6 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
136133 }
137134
138135 function blockNormal ( stream , state ) {
139-
140136 var sol = stream . sol ( ) ;
141137
142138 var prevLineIsList = state . list !== false ,
@@ -158,15 +154,11 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
158154 }
159155
160156 var match = null ;
161- if ( state . indentationDiff >= 4 ) {
157+ if ( state . indentationDiff >= 4 && ( prevLineIsIndentedCode || lineIsEmpty ( state . prevLine ) ) ) {
162158 stream . skipToEnd ( ) ;
163- if ( prevLineIsIndentedCode || lineIsEmpty ( state . prevLine ) ) {
164- state . indentation -= 4 ;
165- state . indentedCode = true ;
166- return tokenTypes . code ;
167- } else {
168- return null ;
169- }
159+ state . indentation -= 4 ;
160+ state . indentedCode = true ;
161+ return tokenTypes . code ;
170162 } else if ( stream . eatSpace ( ) ) {
171163 return null ;
172164 } else if ( ( match = stream . match ( atxHeaderRE ) ) && match [ 1 ] . length <= 6 ) {
@@ -390,9 +382,6 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
390382 return getType ( state ) ;
391383 }
392384
393- // Get sol() value now, before character is consumed
394- var sol = stream . sol ( ) ;
395-
396385 var ch = stream . next ( ) ;
397386
398387 // Matches link titles present on next line
@@ -402,7 +391,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
402391 if ( ch === '(' ) {
403392 matchCh = ')' ;
404393 }
405- matchCh = ( matchCh + '' ) . replace ( / ( [ . ? * + ^ $ [ \] \\ ( ) { } | - ] ) / g, "\\$1" ) ;
394+ matchCh = ( matchCh + '' ) . replace ( / ( [ . ? * + ^ \ [\] \\ ( ) { } | - ] ) / g, "\\$1" ) ;
406395 var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh ;
407396 if ( stream . match ( new RegExp ( regex ) , true ) ) {
408397 return tokenTypes . linkHref ;
@@ -483,13 +472,13 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
483472 return type ;
484473 }
485474
486- if ( ch === '[' && stream . match ( / [ ^ \] ] * \] ( \( . * \) | ? \[ . * ? \] ) / , false ) && ! state . image ) {
475+ if ( ch === '[' && ! state . image ) {
487476 state . linkText = true ;
488477 if ( modeCfg . highlightFormatting ) state . formatting = "link" ;
489478 return getType ( state ) ;
490479 }
491480
492- if ( ch === ']' && state . linkText && stream . match ( / \( . * ? \) | ? \[ . * ? \] / , false ) ) {
481+ if ( ch === ']' && state . linkText ) {
493482 if ( modeCfg . highlightFormatting ) state . formatting = "link" ;
494483 var type = getType ( state ) ;
495484 state . linkText = false ;
@@ -535,41 +524,34 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
535524 if ( ch === '<' && stream . match ( / ^ \/ \w * ?> / ) ) {
536525 state . md_inside = false ;
537526 return "tag" ;
538- }
539-
540- var ignoreUnderscore = false ;
541- if ( ! modeCfg . underscoresBreakWords ) {
542- if ( ch === '_' && stream . peek ( ) !== '_' && stream . match ( / ( \w ) / , false ) ) {
543- var prevPos = stream . pos - 2 ;
544- if ( prevPos >= 0 ) {
545- var prevCh = stream . string . charAt ( prevPos ) ;
546- if ( prevCh !== '_' && prevCh . match ( / ( \w ) / , false ) ) {
547- ignoreUnderscore = true ;
548- }
549- }
527+ } else if ( ch === "*" || ch === "_" ) {
528+ var len = 1 , before = stream . pos == 1 ? " " : stream . string . charAt ( stream . pos - 2 )
529+ while ( len < 3 && stream . eat ( ch ) ) len ++
530+ var after = stream . peek ( ) || " "
531+ // See http://spec.commonmark.org/0.27/#emphasis-and-strong-emphasis
532+ var leftFlanking = ! / \s / . test ( after ) && ( ! punctuation . test ( after ) || / \s / . test ( before ) || punctuation . test ( before ) )
533+ var rightFlanking = ! / \s / . test ( before ) && ( ! punctuation . test ( before ) || / \s / . test ( after ) || punctuation . test ( after ) )
534+ var setEm = null , setStrong = null
535+ if ( len % 2 ) { // Em
536+ if ( ! state . em && leftFlanking && ( ch === "*" || ! rightFlanking || punctuation . test ( before ) ) )
537+ setEm = true
538+ else if ( state . em == ch && rightFlanking && ( ch === "*" || ! leftFlanking || punctuation . test ( after ) ) )
539+ setEm = false
550540 }
551- }
552- if ( ch === '*' || ( ch === '_' && ! ignoreUnderscore ) ) {
553- if ( sol && stream . peek ( ) === ' ' ) {
554- // Do nothing, surrounded by newline and space
555- } else if ( state . strong === ch && stream . eat ( ch ) ) { // Remove STRONG
556- if ( modeCfg . highlightFormatting ) state . formatting = "strong" ;
557- var t = getType ( state ) ;
558- state . strong = false ;
559- return t ;
560- } else if ( ! state . strong && stream . eat ( ch ) ) { // Add STRONG
561- state . strong = ch ;
562- if ( modeCfg . highlightFormatting ) state . formatting = "strong" ;
563- return getType ( state ) ;
564- } else if ( state . em === ch ) { // Remove EM
565- if ( modeCfg . highlightFormatting ) state . formatting = "em" ;
566- var t = getType ( state ) ;
567- state . em = false ;
568- return t ;
569- } else if ( ! state . em ) { // Add EM
570- state . em = ch ;
571- if ( modeCfg . highlightFormatting ) state . formatting = "em" ;
572- return getType ( state ) ;
541+ if ( len > 1 ) { // Strong
542+ if ( ! state . strong && leftFlanking && ( ch === "*" || ! rightFlanking || punctuation . test ( before ) ) )
543+ setStrong = true
544+ else if ( state . strong == ch && rightFlanking && ( ch === "*" || ! leftFlanking || punctuation . test ( after ) ) )
545+ setStrong = false
546+ }
547+ if ( setStrong != null || setEm != null ) {
548+ if ( modeCfg . highlightFormatting ) state . formatting = setEm == null ? "strong" : setStrong == null ? "em" : "strong em"
549+ if ( setEm === true ) state . em = ch
550+ if ( setStrong === true ) state . strong = ch
551+ var t = getType ( state )
552+ if ( setEm === false ) state . em = false
553+ if ( setStrong === false ) state . strong = false
554+ return t
573555 }
574556 } else if ( ch === ' ' ) {
575557 if ( stream . eat ( '*' ) || stream . eat ( '_' ) ) { // Probably surrounded by spaces
@@ -642,7 +624,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
642624 }
643625 var ch = stream . next ( ) ;
644626 if ( ch === '(' || ch === '[' ) {
645- state . f = state . inline = getLinkHrefInside ( ch === "(" ? ")" : "]" , 0 ) ;
627+ state . f = state . inline = getLinkHrefInside ( ch === "(" ? ")" : "]" ) ;
646628 if ( modeCfg . highlightFormatting ) state . formatting = "link-string" ;
647629 state . linkHref = true ;
648630 return getType ( state ) ;
@@ -652,7 +634,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
652634
653635 var linkRE = {
654636 ")" : / ^ (?: [ ^ \\ \( \) ] | \\ .| \( (?: [ ^ \\ \( \) ] | \\ .) * \) ) * ?(? = \) ) / ,
655- "]" : / ^ (?: [ ^ \\ \[ \] ] | \\ .| \[ (?: [ ^ \\ \[ \\ ] ] | \\ .) * \] ) * ?(? = \] ) /
637+ "]" : / ^ (?: [ ^ \\ \[ \] ] | \\ .| \[ (?: [ ^ \\ \[ \] ] | \\ .) * \] ) * ?(? = \] ) /
656638 }
657639
658640 function getLinkHrefInside ( endChar ) {
@@ -768,6 +750,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
768750 inline : s . inline ,
769751 text : s . text ,
770752 formatting : false ,
753+ linkText : s . linkText ,
771754 linkTitle : s . linkTitle ,
772755 code : s . code ,
773756 math : s . math ,
0 commit comments