Skip to content

Commit 7126694

Browse files
committed
Resolve link references before creating setext header.
A setext header line after a link reference should not create a header, according to the spec. See commonmark/commonmark-spec#395.
1 parent 6122d5c commit 7126694

File tree

1 file changed

+32
-13
lines changed

1 file changed

+32
-13
lines changed

src/blocks.c

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -229,11 +229,30 @@ static bool S_ends_with_blank_line(cmark_node *node) {
229229
}
230230
}
231231

232+
// returns true if content remains after link defs are resolved.
233+
static bool resolve_reference_link_definitions(
234+
cmark_parser *parser,
235+
cmark_node *b) {
236+
bufsize_t pos;
237+
cmark_strbuf *node_content = &b->content;
238+
cmark_chunk chunk = {node_content->ptr, node_content->size, 0};
239+
while (chunk.len && chunk.data[0] == '[' &&
240+
(pos = cmark_parse_reference_inline(parser->mem, &chunk,
241+
parser->refmap))) {
242+
243+
chunk.data += pos;
244+
chunk.len -= pos;
245+
}
246+
cmark_strbuf_drop(node_content, (node_content->size - chunk.len));
247+
return !is_blank(&b->content, 0);
248+
}
249+
232250
static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
233251
bufsize_t pos;
234252
cmark_node *item;
235253
cmark_node *subitem;
236254
cmark_node *parent;
255+
bool has_content;
237256

238257
parent = b->parent;
239258
assert(b->flags &
@@ -263,15 +282,8 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
263282
switch (S_type(b)) {
264283
case CMARK_NODE_PARAGRAPH:
265284
{
266-
cmark_chunk chunk = {node_content->ptr, node_content->size, 0};
267-
while (chunk.len && chunk.data[0] == '[' &&
268-
(pos = cmark_parse_reference_inline(parser->mem, &chunk, parser->refmap))) {
269-
270-
chunk.data += pos;
271-
chunk.len -= pos;
272-
}
273-
cmark_strbuf_drop(node_content, (node_content->size - chunk.len));
274-
if (is_blank(node_content, 0)) {
285+
has_content = resolve_reference_link_definitions(parser, b);
286+
if (!has_content) {
275287
// remove blank node (former reference def)
276288
cmark_node_free(b);
277289
}
@@ -905,6 +917,7 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
905917
bufsize_t matched = 0;
906918
int lev = 0;
907919
bool save_partially_consumed_tab;
920+
bool has_content;
908921
int save_offset;
909922
int save_column;
910923

@@ -977,10 +990,16 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
977990
} else if (!indented && cont_type == CMARK_NODE_PARAGRAPH &&
978991
(lev =
979992
scan_setext_heading_line(input, parser->first_nonspace))) {
980-
(*container)->type = (uint16_t)CMARK_NODE_HEADING;
981-
(*container)->as.heading.level = lev;
982-
(*container)->as.heading.setext = true;
983-
S_advance_offset(parser, input, input->len - 1 - parser->offset, false);
993+
// finalize paragraph, resolving reference links
994+
has_content = resolve_reference_link_definitions(parser, *container);
995+
996+
if (has_content) {
997+
998+
(*container)->type = (uint16_t)CMARK_NODE_HEADING;
999+
(*container)->as.heading.level = lev;
1000+
(*container)->as.heading.setext = true;
1001+
S_advance_offset(parser, input, input->len - 1 - parser->offset, false);
1002+
}
9841003
} else if (!indented &&
9851004
!(cont_type == CMARK_NODE_PARAGRAPH && !all_matched) &&
9861005
(parser->thematic_break_kill_pos <= parser->first_nonspace) &&

0 commit comments

Comments
 (0)