diff options
Diffstat (limited to 'src/blocks.c')
-rw-r--r-- | src/blocks.c | 67 |
1 files changed, 40 insertions, 27 deletions
diff --git a/src/blocks.c b/src/blocks.c index b21f800..5c04fc0 100644 --- a/src/blocks.c +++ b/src/blocks.c @@ -222,24 +222,6 @@ static bool ends_with_blank_line(cmark_node *node) { return false; } -// Break out of all containing lists -static int break_out_of_lists(cmark_parser *parser, cmark_node **bptr) { - cmark_node *container = *bptr; - cmark_node *b = parser->root; - // find first containing NODE_LIST: - while (b && S_type(b) != CMARK_NODE_LIST) { - b = b->last_child; - } - if (b) { - while (container && container != b) { - container = finalize(parser, container); - } - finalize(parser, b); - *bptr = b->parent; - } - return 0; -} - static cmark_node *finalize(cmark_parser *parser, cmark_node *b) { bufsize_t pos; cmark_node *item; @@ -401,10 +383,12 @@ static void process_inlines(cmark_mem *mem, cmark_node *root, // On success, returns length of the marker, and populates // data with the details. On failure, returns 0. static bufsize_t parse_list_marker(cmark_mem *mem, cmark_chunk *input, - bufsize_t pos, cmark_list **dataptr) { + bufsize_t pos, bool interrupts_paragraph, + cmark_list **dataptr) { unsigned char c; bufsize_t startpos; cmark_list *data; + bufsize_t i; startpos = pos; c = peek_at(input, pos); @@ -414,6 +398,18 @@ static bufsize_t parse_list_marker(cmark_mem *mem, cmark_chunk *input, if (!cmark_isspace(peek_at(input, pos))) { return 0; } + + if (interrupts_paragraph) { + i = pos; + // require non-blank content after list marker: + while (S_is_space_or_tab(peek_at(input, i))) { + i++; + } + if (peek_at(input, i) == '\n') { + return 0; + } + } + data = (cmark_list *)mem->calloc(1, sizeof(*data)); data->marker_offset = 0; // will be adjusted later data->list_type = CMARK_BULLET_LIST; @@ -434,12 +430,26 @@ static bufsize_t parse_list_marker(cmark_mem *mem, cmark_chunk *input, // This also seems to be the limit for 'start' in some browsers. } while (digits < 9 && cmark_isdigit(peek_at(input, pos))); + if (interrupts_paragraph && start != 1) { + return 0; + } c = peek_at(input, pos); if (c == '.' || c == ')') { pos++; if (!cmark_isspace(peek_at(input, pos))) { return 0; } + if (interrupts_paragraph) { + // require non-blank content after list marker: + i = pos; + while (S_is_space_or_tab(peek_at(input, i))) { + i++; + } + if (S_is_line_end_char(peek_at(input, i))) { + return 0; + } + } + data = (cmark_list *)mem->calloc(1, sizeof(*data)); data->marker_offset = 0; // will be adjusted later data->list_type = CMARK_ORDERED_LIST; @@ -852,6 +862,8 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container, if (!indented && peek_at(input, parser->first_nonspace) == '>') { + bufsize_t blockquote_startpos = parser->first_nonspace; + S_advance_offset(parser, input, parser->first_nonspace + 1 - parser->offset, false); // optional following character @@ -859,18 +871,19 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container, S_advance_offset(parser, input, 1, true); } *container = add_child(parser, *container, CMARK_NODE_BLOCK_QUOTE, - parser->offset + 1); + blockquote_startpos + 1); } else if (!indented && (matched = scan_atx_heading_start( input, parser->first_nonspace))) { bufsize_t hashpos; int level = 0; + bufsize_t heading_startpos = parser->first_nonspace; S_advance_offset(parser, input, parser->first_nonspace + matched - parser->offset, false); *container = - add_child(parser, *container, CMARK_NODE_HEADING, parser->offset + 1); + add_child(parser, *container, CMARK_NODE_HEADING, heading_startpos + 1); hashpos = cmark_chunk_strchr(input, '#', parser->first_nonspace); @@ -921,8 +934,12 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container, parser->first_nonspace + 1); S_advance_offset(parser, input, input->len - 1 - parser->offset, false); } else if ((matched = parse_list_marker(parser->mem, input, - parser->first_nonspace, &data)) && - (!indented || cont_type == CMARK_NODE_LIST)) { + parser->first_nonspace, + (*container)->type == + CMARK_NODE_PARAGRAPH, + &data)) && + (!indented || cont_type == CMARK_NODE_LIST)) { + // Note that we can have new list items starting with >= 4 // spaces indent, as long as the list container is still open. int i = 0; @@ -1146,10 +1163,6 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer, container = last_matched_container; - // check to see if we've hit 2nd blank line, break out of list: - if (parser->blank && S_last_line_blank(container)) - break_out_of_lists(parser, &container); - open_new_blocks(parser, &container, &input, all_matched); add_text_to_container(parser, container, last_matched_container, &input); |