diff --git a/api_test/main.c b/api_test/main.c index 0df1a7d8d..0a31151b3 100644 --- a/api_test/main.c +++ b/api_test/main.c @@ -526,6 +526,13 @@ static void test_content(test_batch_runner *runner, cmark_node_type type, static void parser(test_batch_runner *runner) { test_md_to_html(runner, "No newline", "
No newline
\n", "document without trailing newline"); + + // Only spaces are removed before a soft line break; a trailing tab is + // kept, matching the spec (which strips only end-of-line spaces). + test_md_to_html(runner, "foo\t\nbar\n", "foo\t\nbar
\n", + "trailing tab kept before soft line break"); + test_md_to_html(runner, "foo \nbar\n", "foo\nbar
\n", + "trailing space removed before soft line break"); } static void render_html(test_batch_runner *runner) { diff --git a/src/inlines.c b/src/inlines.c index 8c9564dd0..7d16ff7fa 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -1399,9 +1399,12 @@ static int parse_inline(subject *subj, cmark_node *parent, int options) { startpos = subj->pos; subj->pos = endpos; - // if we're at a newline, strip trailing spaces. + // if we're at a newline, strip trailing spaces. Only spaces are + // removed before a line ending; trailing tabs are preserved, as the + // spec strips only spaces at the end of a line (a final tab is kept). if (S_is_line_end_char(peek_char(subj))) { - cmark_chunk_rtrim(&contents); + while (contents.len > 0 && contents.data[contents.len - 1] == ' ') + contents.len--; } new_inl = make_str(subj, startpos, endpos - 1, contents);