Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions api_test/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,26 @@ static void render_latex(test_batch_runner *runner) {
"enumerate counter ignores bullet list nesting");
free(latex);
cmark_node_free(nested_doc);

// A code block containing \end{verbatim} must not close the verbatim
// environment and let the following lines be read as LaTeX.
static const char code[] = " a\n"
" \\end{verbatim}\n"
" \\input{secret}\n";
cmark_node *code_doc =
cmark_parse_document(code, sizeof(code) - 1, CMARK_OPT_DEFAULT);
latex = cmark_render_latex(code_doc, CMARK_OPT_DEFAULT, 0);
STR_EQ(runner, latex,
"\\begin{verbatim}\n"
"a\n"
"\\end{verbatim}\n"
"\\texttt{\\textbackslash{}end\\{verbatim\\}}\n"
"\\begin{verbatim}\n"
"\\input{secret}\n"
"\\end{verbatim}\n",
"escape \\end{verbatim} inside code block");
free(latex);
cmark_node_free(code_doc);
}

static void render_commonmark(test_batch_runner *runner) {
Expand Down
32 changes: 31 additions & 1 deletion src/latex.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,36 @@ static int S_get_enumlevel(cmark_node *node) {
return enumlevel;
}

// A literal \end{verbatim} would close the environment early and the
// rest of the code block would be read as LaTeX, so close the environment
// before each occurrence, print it escaped, and reopen.
static void S_render_verbatim(cmark_renderer *renderer, const char *code) {
static const char end_verbatim[] = "\\end{verbatim}";
const char *match;
cmark_strbuf buf = CMARK_BUF_INIT(renderer->mem);

while ((match = strstr(code, end_verbatim)) != NULL) {
cmark_strbuf_set(&buf, (const unsigned char *)code,
(bufsize_t)(match - code));
OUT((const char *)buf.ptr, false, LITERAL);
CR();
LIT("\\end{verbatim}");
CR();
LIT("\\texttt{");
OUT(end_verbatim, false, NORMAL);
LIT("}");
CR();
LIT("\\begin{verbatim}");
CR();
code = match + sizeof(end_verbatim) - 1;
if (*code == '\n') {
code++;
}
}
OUT(code, false, LITERAL);
cmark_strbuf_free(&buf);
}

static int S_render_node(cmark_renderer *renderer, cmark_node *node,
cmark_event_type ev_type, int options) {
int list_number;
Expand Down Expand Up @@ -318,7 +348,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
CR();
LIT("\\begin{verbatim}");
CR();
OUT(cmark_node_get_literal(node), false, LITERAL);
S_render_verbatim(renderer, cmark_node_get_literal(node));
CR();
LIT("\\end{verbatim}");
BLANKLINE();
Expand Down
Loading