@@ -787,25 +787,49 @@ var Tokenizer_1 = class Tokenizer {
787
787
}
788
788
}
789
789
790
- strong ( src ) {
791
- const cap = this . rules . inline . strong . exec ( src ) ;
792
- if ( cap ) {
793
- return {
794
- type : 'strong' ,
795
- raw : cap [ 0 ] ,
796
- text : cap [ 4 ] || cap [ 3 ] || cap [ 2 ] || cap [ 1 ]
797
- } ;
790
+ strong ( src , maskedSrc , prevChar = '' ) {
791
+ let match = this . rules . inline . strong . start . exec ( src ) ;
792
+
793
+ if ( match && ( ! match [ 1 ] || ( match [ 1 ] && ( prevChar === '' || this . rules . inline . punctuation . exec ( prevChar ) ) ) ) ) {
794
+ maskedSrc = maskedSrc . slice ( - 1 * src . length ) ;
795
+ const endReg = match [ 0 ] === '**' ? this . rules . inline . strong . endAst : this . rules . inline . strong . endUnd ;
796
+
797
+ endReg . lastIndex = 0 ;
798
+
799
+ let cap ;
800
+ while ( ( match = endReg . exec ( maskedSrc ) ) != null ) {
801
+ cap = this . rules . inline . strong . middle . exec ( maskedSrc . slice ( 0 , match . index + 3 ) ) ;
802
+ if ( cap ) {
803
+ return {
804
+ type : 'strong' ,
805
+ raw : src . slice ( 0 , cap [ 0 ] . length ) ,
806
+ text : src . slice ( 2 , cap [ 0 ] . length - 2 )
807
+ } ;
808
+ }
809
+ }
798
810
}
799
811
}
800
812
801
- em ( src ) {
802
- const cap = this . rules . inline . em . exec ( src ) ;
803
- if ( cap ) {
804
- return {
805
- type : 'em' ,
806
- raw : cap [ 0 ] ,
807
- text : cap [ 6 ] || cap [ 5 ] || cap [ 4 ] || cap [ 3 ] || cap [ 2 ] || cap [ 1 ]
808
- } ;
813
+ em ( src , maskedSrc , prevChar = '' ) {
814
+ let match = this . rules . inline . em . start . exec ( src ) ;
815
+
816
+ if ( match && ( ! match [ 1 ] || ( match [ 1 ] && ( prevChar === '' || this . rules . inline . punctuation . exec ( prevChar ) ) ) ) ) {
817
+ maskedSrc = maskedSrc . slice ( - 1 * src . length ) ;
818
+ const endReg = match [ 0 ] === '*' ? this . rules . inline . em . endAst : this . rules . inline . em . endUnd ;
819
+
820
+ endReg . lastIndex = 0 ;
821
+
822
+ let cap ;
823
+ while ( ( match = endReg . exec ( maskedSrc ) ) != null ) {
824
+ cap = this . rules . inline . em . middle . exec ( maskedSrc . slice ( 0 , match . index + 2 ) ) ;
825
+ if ( cap ) {
826
+ return {
827
+ type : 'em' ,
828
+ raw : src . slice ( 0 , cap [ 0 ] . length ) ,
829
+ text : src . slice ( 1 , cap [ 0 ] . length - 1 )
830
+ } ;
831
+ }
832
+ }
809
833
}
810
834
}
811
835
@@ -1101,19 +1125,74 @@ const inline = {
1101
1125
link : / ^ ! ? \[ ( l a b e l ) \] \( \s * ( h r e f ) (?: \s + ( t i t l e ) ) ? \s * \) / ,
1102
1126
reflink : / ^ ! ? \[ ( l a b e l ) \] \[ (? ! \s * \] ) ( (?: \\ [ \[ \] ] ? | [ ^ \[ \] \\ ] ) + ) \] / ,
1103
1127
nolink : / ^ ! ? \[ (? ! \s * \] ) ( (?: \[ [ ^ \[ \] ] * \] | \\ [ \[ \] ] | [ ^ \[ \] ] ) * ) \] (?: \[ \] ) ? / ,
1104
- strong : / ^ _ _ ( [ ^ \s _ ] ) _ _ (? ! _ ) | ^ \* \* ( [ ^ \s * ] ) \* \* (? ! \* ) | ^ _ _ ( [ ^ \s ] [ \s \S ] * ?[ ^ \s ] ) _ _ (? ! _ ) | ^ \* \* ( [ ^ \s ] [ \s \S ] * ?[ ^ \s ] ) \* \* (? ! \* ) / ,
1105
- em : / ^ _ ( [ ^ \s _ ] ) _ (? ! _ ) | ^ _ ( [ ^ \s _ < ] [ \s \S ] * ?[ ^ \s _ ] ) _ (? ! _ | [ ^ \s , p u n c t u a t i o n ] ) | ^ _ ( [ ^ \s _ < ] [ \s \S ] * ?[ ^ \s ] ) _ (? ! _ | [ ^ \s , p u n c t u a t i o n ] ) | ^ \* ( [ ^ \s * < \[ ] ) \* (? ! \* ) | ^ \* ( [ ^ \s < " ] [ \s \S ] * ?[ ^ \s \[ \* ] ) \* (? ! [ \] ` p u n c t u a t i o n ] ) | ^ \* ( [ ^ \s * " < \[ ] [ \s \S ] * [ ^ \s ] ) \* (? ! \* ) / ,
1128
+ reflinkSearch : 'reflink|nolink(?!\\()' ,
1129
+ strong : {
1130
+ start : / ^ (?: ( \* \* (? = [ * p u n c t u a t i o n ] ) ) | \* \* ) (? ! [ \s ] ) | _ _ / , // (1) returns if starts w/ punctuation
1131
+ middle : / ^ \* \* (?: (?: (? ! o v e r l a p S k i p ) (?: [ ^ * ] | \\ \* ) | o v e r l a p S k i p ) | \* (?: (? ! o v e r l a p S k i p ) (?: [ ^ * ] | \\ \* ) | o v e r l a p S k i p ) * ?\* ) + ?\* \* $ | ^ _ _ (? ! [ \s ] ) ( (?: (?: (? ! o v e r l a p S k i p ) (?: [ ^ _ ] | \\ _ ) | o v e r l a p S k i p ) | _ (?: (? ! o v e r l a p S k i p ) (?: [ ^ _ ] | \\ _ ) | o v e r l a p S k i p ) * ?_ ) + ?) _ _ $ / ,
1132
+ endAst : / [ ^ p u n c t u a t i o n \s ] \* \* (? ! \* ) | [ p u n c t u a t i o n ] \* \* (? ! \* ) (?: (? = [ p u n c t u a t i o n \s ] | $ ) ) / , // last char can't be punct, or final * must also be followed by punct (or endline)
1133
+ endUnd : / [ ^ \s ] _ _ (? ! _ ) (?: (? = [ p u n c t u a t i o n \s ] ) | $ ) / // last char can't be a space, and final _ must preceed punct or \s (or endline)
1134
+ } ,
1135
+ em : {
1136
+ start : / ^ (?: ( \* (? = [ p u n c t u a t i o n ] ) ) | \* ) (? ! [ * \s ] ) | _ / , // (1) returns if starts w/ punctuation
1137
+ middle : / ^ \* (?: (?: (? ! o v e r l a p S k i p ) (?: [ ^ * ] | \\ \* ) | o v e r l a p S k i p ) | \* (?: (? ! o v e r l a p S k i p ) (?: [ ^ * ] | \\ \* ) | o v e r l a p S k i p ) * ?\* ) + ?\* $ | ^ _ (? ! [ _ \s ] ) (?: (?: (? ! o v e r l a p S k i p ) (?: [ ^ _ ] | \\ _ ) | o v e r l a p S k i p ) | _ (?: (? ! o v e r l a p S k i p ) (?: [ ^ _ ] | \\ _ ) | o v e r l a p S k i p ) * ?_ ) + ?_ $ / ,
1138
+ endAst : / [ ^ p u n c t u a t i o n \s ] \* (? ! \* ) | [ p u n c t u a t i o n ] \* (? ! \* ) (?: (? = [ p u n c t u a t i o n \s ] | $ ) ) / , // last char can't be punct, or final * must also be followed by punct (or endline)
1139
+ endUnd : / [ ^ \s ] _ (? ! _ ) (?: (? = [ p u n c t u a t i o n \s ] ) | $ ) / // last char can't be a space, and final _ must preceed punct or \s (or endline)
1140
+ } ,
1106
1141
code : / ^ ( ` + ) ( [ ^ ` ] | [ ^ ` ] [ \s \S ] * ?[ ^ ` ] ) \1(? ! ` ) / ,
1107
1142
br : / ^ ( { 2 , } | \\ ) \n (? ! \s * $ ) / ,
1108
1143
del : noopTest$1 ,
1109
- text : / ^ ( ` + | [ ^ ` ] ) (?: [ \s \S ] * ?(?: (? = [ \\ < ! \[ ` * ] | \b _ | $ ) | [ ^ ] (? = { 2 , } \n ) ) | (? = { 2 , } \n ) ) /
1144
+ text : / ^ ( ` + | [ ^ ` ] ) (?: [ \s \S ] * ?(?: (? = [ \\ < ! \[ ` * ] | \b _ | $ ) | [ ^ ] (? = { 2 , } \n ) ) | (? = { 2 , } \n ) ) / ,
1145
+ punctuation : / ^ ( [ \s * p u n c t u a t i o n ] ) /
1110
1146
} ;
1111
1147
1112
1148
// list of punctuation marks from common mark spec
1113
- // without ` and ] to workaround Rule 17 (inline code blocks/links)
1114
- // without , to work around example 393
1115
- inline . _punctuation = '!"#$%&\'()*+\\-./:;<=>?@\\[^_{|}~' ;
1116
- inline . em = edit$1 ( inline . em ) . replace ( / p u n c t u a t i o n / g, inline . _punctuation ) . getRegex ( ) ;
1149
+ // without * and _ to workaround cases with double emphasis
1150
+ inline . _punctuation = '!"#$%&\'()+\\-.,/:;<=>?@\\[\\]`^{|}~' ;
1151
+ inline . punctuation = edit$1 ( inline . punctuation ) . replace ( / p u n c t u a t i o n / g, inline . _punctuation ) . getRegex ( ) ;
1152
+
1153
+ // sequences em should skip over [title](link), `code`, <html>
1154
+ inline . _blockSkip = '\\[[^\\]]*?\\]\\([^\\)]*?\\)|`[^`]*?`|<[^>]*?>' ;
1155
+ inline . _overlapSkip = '__[^_]*?__|\\*\\*\\[^\\*\\]*?\\*\\*' ;
1156
+
1157
+ inline . em . start = edit$1 ( inline . em . start )
1158
+ . replace ( / p u n c t u a t i o n / g, inline . _punctuation )
1159
+ . getRegex ( ) ;
1160
+
1161
+ inline . em . middle = edit$1 ( inline . em . middle )
1162
+ . replace ( / p u n c t u a t i o n / g, inline . _punctuation )
1163
+ . replace ( / o v e r l a p S k i p / g, inline . _overlapSkip )
1164
+ . getRegex ( ) ;
1165
+
1166
+ inline . em . endAst = edit$1 ( inline . em . endAst , 'g' )
1167
+ . replace ( / p u n c t u a t i o n / g, inline . _punctuation )
1168
+ . getRegex ( ) ;
1169
+
1170
+ inline . em . endUnd = edit$1 ( inline . em . endUnd , 'g' )
1171
+ . replace ( / p u n c t u a t i o n / g, inline . _punctuation )
1172
+ . getRegex ( ) ;
1173
+
1174
+ inline . strong . start = edit$1 ( inline . strong . start )
1175
+ . replace ( / p u n c t u a t i o n / g, inline . _punctuation )
1176
+ . getRegex ( ) ;
1177
+
1178
+ inline . strong . middle = edit$1 ( inline . strong . middle )
1179
+ . replace ( / p u n c t u a t i o n / g, inline . _punctuation )
1180
+ . replace ( / b l o c k S k i p / g, inline . _blockSkip )
1181
+ . getRegex ( ) ;
1182
+
1183
+ inline . strong . endAst = edit$1 ( inline . strong . endAst , 'g' )
1184
+ . replace ( / p u n c t u a t i o n / g, inline . _punctuation )
1185
+ . getRegex ( ) ;
1186
+
1187
+ inline . strong . endUnd = edit$1 ( inline . strong . endUnd , 'g' )
1188
+ . replace ( / p u n c t u a t i o n / g, inline . _punctuation )
1189
+ . getRegex ( ) ;
1190
+
1191
+ inline . blockSkip = edit$1 ( inline . _blockSkip , 'g' )
1192
+ . getRegex ( ) ;
1193
+
1194
+ inline . overlapSkip = edit$1 ( inline . _overlapSkip , 'g' )
1195
+ . getRegex ( ) ;
1117
1196
1118
1197
inline . _escapes = / \\ ( [ ! " # $ % & ' ( ) * + , \- . / : ; < = > ? @ \[ \] \\ ^ _ ` { | } ~ ] ) / g;
1119
1198
@@ -1145,6 +1224,11 @@ inline.reflink = edit$1(inline.reflink)
1145
1224
. replace ( 'label' , inline . _label )
1146
1225
. getRegex ( ) ;
1147
1226
1227
+ inline . reflinkSearch = edit$1 ( inline . reflinkSearch , 'g' )
1228
+ . replace ( 'reflink' , inline . reflink )
1229
+ . replace ( 'nolink' , inline . nolink )
1230
+ . getRegex ( ) ;
1231
+
1148
1232
/**
1149
1233
* Normal Inline Grammar
1150
1234
*/
@@ -1156,8 +1240,18 @@ inline.normal = merge$1({}, inline);
1156
1240
*/
1157
1241
1158
1242
inline . pedantic = merge$1 ( { } , inline . normal , {
1159
- strong : / ^ _ _ (? = \S ) ( [ \s \S ] * ?\S ) _ _ (? ! _ ) | ^ \* \* (? = \S ) ( [ \s \S ] * ?\S ) \* \* (? ! \* ) / ,
1160
- em : / ^ _ (? = \S ) ( [ \s \S ] * ?\S ) _ (? ! _ ) | ^ \* (? = \S ) ( [ \s \S ] * ?\S ) \* (? ! \* ) / ,
1243
+ strong : {
1244
+ start : / ^ _ _ | \* \* / ,
1245
+ middle : / ^ _ _ (? = \S ) ( [ \s \S ] * ?\S ) _ _ (? ! _ ) | ^ \* \* (? = \S ) ( [ \s \S ] * ?\S ) \* \* (? ! \* ) / ,
1246
+ endAst : / \* \* (? ! \* ) / g,
1247
+ endUnd : / _ _ (? ! _ ) / g
1248
+ } ,
1249
+ em : {
1250
+ start : / ^ _ | \* / ,
1251
+ middle : / ^ ( ) \* (? = \S ) ( [ \s \S ] * ?\S ) \* (? ! \* ) | ^ _ (? = \S ) ( [ \s \S ] * ?\S ) _ (? ! _ ) / ,
1252
+ endAst : / \* (? ! \* ) / g,
1253
+ endUnd : / _ (? ! _ ) / g
1254
+ } ,
1161
1255
link : edit$1 ( / ^ ! ? \[ ( l a b e l ) \] \( ( .* ?) \) / )
1162
1256
. replace ( 'label' , inline . _label )
1163
1257
. getRegex ( ) ,
@@ -1516,9 +1610,29 @@ var Lexer_1 = class Lexer {
1516
1610
/**
1517
1611
* Lexing/Compiling
1518
1612
*/
1519
- inlineTokens ( src , tokens = [ ] , inLink = false , inRawBlock = false ) {
1613
+ inlineTokens ( src , tokens = [ ] , inLink = false , inRawBlock = false , prevChar = '' ) {
1520
1614
let token ;
1521
1615
1616
+ // String with links masked to avoid interference with em and strong
1617
+ let maskedSrc = src ;
1618
+ let match ;
1619
+
1620
+ // Mask out reflinks
1621
+ if ( this . tokens . links ) {
1622
+ const links = Object . keys ( this . tokens . links ) ;
1623
+ if ( links . length > 0 ) {
1624
+ while ( ( match = this . tokenizer . rules . inline . reflinkSearch . exec ( maskedSrc ) ) != null ) {
1625
+ if ( links . includes ( match [ 0 ] . slice ( match [ 0 ] . lastIndexOf ( '[' ) + 1 , - 1 ) ) ) {
1626
+ maskedSrc = maskedSrc . slice ( 0 , match . index ) + '[' + 'a' . repeat ( match [ 0 ] . length - 2 ) + ']' + maskedSrc . slice ( this . tokenizer . rules . inline . reflinkSearch . lastIndex ) ;
1627
+ }
1628
+ }
1629
+ }
1630
+ }
1631
+ // Mask out other blocks
1632
+ while ( ( match = this . tokenizer . rules . inline . blockSkip . exec ( maskedSrc ) ) != null ) {
1633
+ maskedSrc = maskedSrc . slice ( 0 , match . index ) + '[' + 'a' . repeat ( match [ 0 ] . length - 2 ) + ']' + maskedSrc . slice ( this . tokenizer . rules . inline . blockSkip . lastIndex ) ;
1634
+ }
1635
+
1522
1636
while ( src ) {
1523
1637
// escape
1524
1638
if ( token = this . tokenizer . escape ( src ) ) {
@@ -1557,15 +1671,15 @@ var Lexer_1 = class Lexer {
1557
1671
}
1558
1672
1559
1673
// strong
1560
- if ( token = this . tokenizer . strong ( src ) ) {
1674
+ if ( token = this . tokenizer . strong ( src , maskedSrc , prevChar ) ) {
1561
1675
src = src . substring ( token . raw . length ) ;
1562
1676
token . tokens = this . inlineTokens ( token . text , [ ] , inLink , inRawBlock ) ;
1563
1677
tokens . push ( token ) ;
1564
1678
continue ;
1565
1679
}
1566
1680
1567
1681
// em
1568
- if ( token = this . tokenizer . em ( src ) ) {
1682
+ if ( token = this . tokenizer . em ( src , maskedSrc , prevChar ) ) {
1569
1683
src = src . substring ( token . raw . length ) ;
1570
1684
token . tokens = this . inlineTokens ( token . text , [ ] , inLink , inRawBlock ) ;
1571
1685
tokens . push ( token ) ;
@@ -1611,6 +1725,7 @@ var Lexer_1 = class Lexer {
1611
1725
// text
1612
1726
if ( token = this . tokenizer . inlineText ( src , inRawBlock , smartypants ) ) {
1613
1727
src = src . substring ( token . raw . length ) ;
1728
+ prevChar = token . raw . slice ( - 1 ) ;
1614
1729
tokens . push ( token ) ;
1615
1730
continue ;
1616
1731
}
0 commit comments