From 3ebcf54d5248eee343941fc875509a1c585de5ba Mon Sep 17 00:00:00 2001 From: zayeem shaikh Date: Tue, 20 Oct 2026 23:52:09 +0530 Subject: [PATCH] size tilde code fences by the longest tilde run in commonmark renderer When a code block's info string contains a backtick, the commonmark renderer writes a tilde fence, but it still sized the fence from the longest run of backticks in the code. A line of three or more tildes inside the code then closes the fence early, and the rest of the code block is parsed as Markdown when the output is read back. Count runs of the fence character actually used. --- api_test/main.c | 15 +++++++++++++++ src/commonmark.c | 6 +++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/api_test/main.c b/api_test/main.c index 0df1a7d8d..7e32ee79b 100644 --- a/api_test/main.c +++ b/api_test/main.c @@ -804,6 +804,21 @@ static void render_commonmark(test_batch_runner *runner) { free(commonmark); cmark_node_free(plain_break_doc); + // An info string containing a backtick forces a tilde fence, which must + // be longer than any run of tildes in the code. + static const char tilde_fence[] = "~~~~~ a`b\n" + "~~~\n" + "x\n" + "~~~~~\n"; + cmark_node *tilde_fence_doc = + cmark_parse_document(tilde_fence, sizeof(tilde_fence) - 1, + CMARK_OPT_DEFAULT); + commonmark = cmark_render_commonmark(tilde_fence_doc, CMARK_OPT_DEFAULT, 0); + STR_EQ(runner, commonmark, "~~~~ a`b\n~~~\nx\n~~~~\n", + "render tilde fence longer than tildes in code"); + free(commonmark); + cmark_node_free(tilde_fence_doc); + cmark_node_free(text); cmark_node_free(doc); } diff --git a/src/commonmark.c b/src/commonmark.c index 44ee695d2..1b6268f3f 100644 --- a/src/commonmark.c +++ b/src/commonmark.c @@ -73,13 +73,13 @@ static inline void outc(cmark_renderer *renderer, cmark_escaping escape, } } -static int longest_backtick_sequence(const char *code) { +static int longest_char_sequence(const char *code, char c) { int longest = 0; int current = 0; size_t i = 0; size_t code_len = strlen(code); while (i <= code_len) { - if (code[i] == '`') { + if (code[i] == c) { current++; } else { if (current > longest) { @@ -281,7 +281,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node, fencechar[0] = strchr(info, '`') == NULL ? '`' : '~'; code = cmark_node_get_literal(node); - numticks = longest_backtick_sequence(code) + 1; + numticks = longest_char_sequence(code, fencechar[0]) + 1; if (numticks < 3) { numticks = 3; }