diff options
| author | John MacFarlane <jgm@berkeley.edu> | 2019-04-06 11:17:07 -0700 | 
|---|---|---|
| committer | John MacFarlane <jgm@berkeley.edu> | 2019-04-06 11:25:47 -0700 | 
| commit | 7126694b85bd1f5ba6533b81b2565f276d1da503 (patch) | |
| tree | 673620b18942b02f3183b6e829bb03180da345e2 /src | |
| parent | 6122d5cc3c5e5e8f94f203daddfd38a36be7aed4 (diff) | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/blocks.c | 45 | 
1 files changed, 32 insertions, 13 deletions
| diff --git a/src/blocks.c b/src/blocks.c index 804ad82..b6077eb 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -229,11 +229,30 @@ static bool S_ends_with_blank_line(cmark_node *node) {    }  } +// returns true if content remains after link defs are resolved. +static bool resolve_reference_link_definitions( +		cmark_parser *parser, +                cmark_node *b) { +  bufsize_t pos; +  cmark_strbuf *node_content = &b->content; +  cmark_chunk chunk = {node_content->ptr, node_content->size, 0}; +  while (chunk.len && chunk.data[0] == '[' && +         (pos = cmark_parse_reference_inline(parser->mem, &chunk, +					     parser->refmap))) { + +    chunk.data += pos; +    chunk.len -= pos; +  } +  cmark_strbuf_drop(node_content, (node_content->size - chunk.len)); +  return !is_blank(&b->content, 0); +} +  static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {    bufsize_t pos;    cmark_node *item;    cmark_node *subitem;    cmark_node *parent; +  bool has_content;    parent = b->parent;    assert(b->flags & @@ -263,15 +282,8 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {    switch (S_type(b)) {    case CMARK_NODE_PARAGRAPH:    { -    cmark_chunk chunk = {node_content->ptr, node_content->size, 0}; -    while (chunk.len && chunk.data[0] == '[' && -           (pos = cmark_parse_reference_inline(parser->mem, &chunk, parser->refmap))) { - -      chunk.data += pos; -      chunk.len -= pos; -    } -    cmark_strbuf_drop(node_content, (node_content->size - chunk.len)); -    if (is_blank(node_content, 0)) { +    has_content = resolve_reference_link_definitions(parser, b); +    if (!has_content) {        // remove blank node (former reference def)        cmark_node_free(b);      } @@ -905,6 +917,7 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,    bufsize_t matched = 0;    int lev = 0;    bool save_partially_consumed_tab; +  bool has_content;    int save_offset;    int save_column; @@ -977,10 +990,16 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,      } else if (!indented && cont_type == CMARK_NODE_PARAGRAPH &&                 (lev =                      scan_setext_heading_line(input, parser->first_nonspace))) { -      (*container)->type = (uint16_t)CMARK_NODE_HEADING; -      (*container)->as.heading.level = lev; -      (*container)->as.heading.setext = true; -      S_advance_offset(parser, input, input->len - 1 - parser->offset, false); +      // finalize paragraph, resolving reference links +      has_content = resolve_reference_link_definitions(parser, *container); + +      if (has_content) { + +        (*container)->type = (uint16_t)CMARK_NODE_HEADING; +        (*container)->as.heading.level = lev; +        (*container)->as.heading.setext = true; +        S_advance_offset(parser, input, input->len - 1 - parser->offset, false); +      }      } else if (!indented &&                 !(cont_type == CMARK_NODE_PARAGRAPH && !all_matched) &&  	       (parser->thematic_break_kill_pos <= parser->first_nonspace) && | 
