@@ -105,6 +105,7 @@ cmark_parser *cmark_parser_new_with_mem(int options, cmark_mem *mem) {
105
105
parser -> column = 0 ;
106
106
parser -> first_nonspace = 0 ;
107
107
parser -> first_nonspace_column = 0 ;
108
+ parser -> thematic_break_kill_pos = 0 ;
108
109
parser -> indent = 0 ;
109
110
parser -> blank = false;
110
111
parser -> partially_consumed_tab = false;
@@ -615,6 +616,40 @@ static void chop_trailing_hashtags(cmark_chunk *ch) {
615
616
}
616
617
}
617
618
619
+ // Check for thematic break. On failure, return 0 and update
620
+ // thematic_break_kill_pos with the index at which the
621
+ // parse fails. On success, return length of match.
622
+ // "...three or more hyphens, asterisks,
623
+ // or underscores on a line by themselves. If you wish, you may use
624
+ // spaces between the hyphens or asterisks."
625
+ static int S_scan_thematic_break (cmark_parser * parser , cmark_chunk * input ,
626
+ bufsize_t offset ) {
627
+ bufsize_t i ;
628
+ char c ;
629
+ char nextc = '\0' ;
630
+ int count ;
631
+ i = offset ;
632
+ c = peek_at (input , i );
633
+ if (!(c == '*' || c == '_' || c == '-' )) {
634
+ parser -> thematic_break_kill_pos = i ;
635
+ return 0 ;
636
+ }
637
+ count = 1 ;
638
+ while ((nextc = peek_at (input , ++ i ))) {
639
+ if (nextc == c ) {
640
+ count ++ ;
641
+ } else if (nextc != ' ' && nextc != '\t' ) {
642
+ break ;
643
+ }
644
+ }
645
+ if (count >= 3 && (nextc == '\r' || nextc == '\n' )) {
646
+ return (i - offset ) + 1 ;
647
+ } else {
648
+ parser -> thematic_break_kill_pos = i ;
649
+ return 0 ;
650
+ }
651
+ }
652
+
618
653
// Find first nonspace character from current offset, setting
619
654
// parser->first_nonspace, parser->first_nonspace_column,
620
655
// parser->indent, and parser->blank. Does not advance parser->offset.
@@ -948,7 +983,8 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
948
983
S_advance_offset (parser , input , input -> len - 1 - parser -> offset , false);
949
984
} else if (!indented &&
950
985
!(cont_type == CMARK_NODE_PARAGRAPH && !all_matched ) &&
951
- (matched = scan_thematic_break (input , parser -> first_nonspace ))) {
986
+ (parser -> thematic_break_kill_pos <= parser -> first_nonspace ) &&
987
+ (matched = S_scan_thematic_break (parser , input , parser -> first_nonspace ))) {
952
988
// it's only now that we know the line is not part of a setext heading:
953
989
* container = add_child (parser , * container , CMARK_NODE_THEMATIC_BREAK ,
954
990
parser -> first_nonspace + 1 );
@@ -1171,6 +1207,7 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
1171
1207
parser -> column = 0 ;
1172
1208
parser -> first_nonspace = 0 ;
1173
1209
parser -> first_nonspace_column = 0 ;
1210
+ parser -> thematic_break_kill_pos = 0 ;
1174
1211
parser -> indent = 0 ;
1175
1212
parser -> blank = false;
1176
1213
parser -> partially_consumed_tab = false;
0 commit comments