@@ -1353,45 +1353,60 @@ is_hrule(uint8_t *data, size_t size)
13531353 return n >= 3 ;
13541354}
13551355
1356- /* check if a line begins with a code fence; return the
1357- * width of the code fence */
1356+ /* check if a line begins with a code fence matching optional opendelim;
1357+ return the width of the code fence and store the delimiter string */
13581358static size_t
1359- prefix_codefence (uint8_t * data , size_t size )
1359+ prefix_codefence (uint8_t * data , size_t size , struct buf * delim , struct buf * opendelim )
13601360{
1361- size_t i = 0 , n = 0 ;
1362- uint8_t c ;
1361+ size_t i = 0 , n = 0 , min_n = 3 ;
1362+ uint8_t c , * delim_start ;
13631363
13641364 /* skipping initial spaces */
13651365 if (size < 3 ) return 0 ;
13661366 if (data [0 ] == ' ' ) { i ++ ;
13671367 if (data [1 ] == ' ' ) { i ++ ;
13681368 if (data [2 ] == ' ' ) { i ++ ; } } }
13691369
1370+ delim_start = data + i ;
1371+
13701372 /* looking at the hrule uint8_t */
13711373 if (i + 2 >= size || !(data [i ] == '~' || data [i ] == '`' ))
13721374 return 0 ;
13731375
1374- c = data [i ];
1376+ if (opendelim && opendelim -> size ) {
1377+ c = opendelim -> data [0 ];
1378+ min_n = opendelim -> size ;
1379+ } else {
1380+ c = data [i ];
1381+ }
13751382
13761383 /* the whole line must be the uint8_t or whitespace */
13771384 while (i < size && data [i ] == c ) {
13781385 n ++ ; i ++ ;
13791386 }
13801387
1381- if (n < 3 )
1388+ if (n < min_n )
13821389 return 0 ;
13831390
1391+ if (delim ) {
1392+ delim -> data = delim_start ;
1393+ delim -> size = n ;
1394+ }
1395+
13841396 return i ;
13851397}
13861398
13871399/* check if a line is a code fence; return its size if it is */
1400+ /* checking is done in fence-pair matching mode if curdelim is provided */
13881401static size_t
1389- is_codefence (uint8_t * data , size_t size , struct buf * syntax )
1402+ is_codefence (uint8_t * data , size_t size , struct buf * curdelim , struct buf * syntax )
13901403{
13911404 size_t i = 0 , syn_len = 0 ;
13921405 uint8_t * syn_start ;
1406+ struct buf delim = { 0 , 0 , 0 , 0 };
1407+
1408+ i = prefix_codefence (data , size , & delim , curdelim );
13931409
1394- i = prefix_codefence (data , size );
13951410 if (i == 0 )
13961411 return 0 ;
13971412
@@ -1426,10 +1441,9 @@ is_codefence(uint8_t *data, size_t size, struct buf *syntax)
14261441 }
14271442 }
14281443
1429- if (syntax ) {
1430- syntax -> data = syn_start ;
1431- syntax -> size = syn_len ;
1432- }
1444+ /* info string must not be present at the closing fence */
1445+ if (curdelim && curdelim -> size && syn_len )
1446+ return 0 ;
14331447
14341448 while (i < size && data [i ] != '\n' ) {
14351449 if (!_isspace (data [i ]))
@@ -1438,6 +1452,21 @@ is_codefence(uint8_t *data, size_t size, struct buf *syntax)
14381452 i ++ ;
14391453 }
14401454
1455+ if (curdelim ) {
1456+ if (curdelim -> size ) {
1457+ curdelim -> data = NULL ;
1458+ curdelim -> size = 0 ;
1459+ } else {
1460+ curdelim -> data = delim .data ;
1461+ curdelim -> size = delim .size ;
1462+ }
1463+ }
1464+
1465+ if (syntax ) {
1466+ syntax -> data = syn_start ;
1467+ syntax -> size = syn_len ;
1468+ }
1469+
14411470 return i + 1 ;
14421471}
14431472
@@ -1673,7 +1702,7 @@ parse_paragraph(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
16731702
16741703 /* see if a code fence starts here */
16751704 if ((rndr -> ext_flags & MKDEXT_FENCED_CODE ) != 0 &&
1676- is_codefence (data + i , size - i , NULL ) != 0 ) {
1705+ is_codefence (data + i , size - i , NULL , NULL ) != 0 ) {
16771706 end = i ;
16781707 break ;
16791708 }
@@ -1739,19 +1768,19 @@ parse_fencedcode(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
17391768{
17401769 size_t beg , end ;
17411770 struct buf * work = 0 ;
1771+ struct buf delim = { 0 , 0 , 0 , 0 };
17421772 struct buf lang = { 0 , 0 , 0 , 0 };
17431773
1744- beg = is_codefence (data , size , & lang );
1774+ beg = is_codefence (data , size , & delim , & lang );
17451775 if (beg == 0 ) return 0 ;
17461776
17471777 work = rndr_newbuf (rndr , BUFFER_BLOCK );
17481778
17491779 while (beg < size ) {
17501780 size_t fence_end ;
1751- struct buf fence_trail = { 0 , 0 , 0 , 0 };
17521781
1753- fence_end = is_codefence (data + beg , size - beg , & fence_trail );
1754- if (fence_end != 0 && fence_trail . size == 0 ) {
1782+ fence_end = is_codefence (data + beg , size - beg , & delim , NULL );
1783+ if (fence_end != 0 ) {
17551784 beg += fence_end ;
17561785 break ;
17571786 }
@@ -1827,6 +1856,7 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t s
18271856 struct buf * work = 0 , * inter = 0 ;
18281857 size_t beg = 0 , end , pre , sublist = 0 , orgpre = 0 , i ;
18291858 int in_empty = 0 , has_inside_empty = 0 , in_fence = 0 ;
1859+ struct buf fence_delim = { 0 , 0 , 0 , 0 };
18301860
18311861 /* keeping track of the first indentation prefix */
18321862 while (orgpre < 3 && orgpre < size && data [orgpre ] == ' ' )
@@ -1876,7 +1906,7 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t s
18761906 pre = i ;
18771907
18781908 if (rndr -> ext_flags & MKDEXT_FENCED_CODE ) {
1879- if (is_codefence (data + beg + i , end - beg - i , NULL ) != 0 )
1909+ if (is_codefence (data + beg + i , end - beg - i , & fence_delim , NULL ) != 0 )
18801910 in_fence = !in_fence ;
18811911 }
18821912
@@ -2804,6 +2834,7 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
28042834 struct buf * text ;
28052835 size_t beg , end ;
28062836 int in_fence = 0 ;
2837+ struct buf fence_delim = { 0 , 0 , 0 , 0 };
28072838
28082839 text = bufnew (64 );
28092840 if (!text )
@@ -2833,7 +2864,7 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
28332864 beg += 3 ;
28342865
28352866 while (beg < doc_size ) { /* iterating over lines */
2836- if (codefences_enabled && (is_codefence (document + beg , doc_size - beg , NULL ) != 0 ))
2867+ if (codefences_enabled && (is_codefence (document + beg , doc_size - beg , & fence_delim , NULL ) != 0 ))
28372868 in_fence = !in_fence ;
28382869
28392870 if (!in_fence && footnotes_enabled && is_footnote (document , beg , doc_size , & end , & md -> footnotes_found ))
0 commit comments