md4c

C Markdown parser. Fast. SAX-like interface. Compliant to CommonMark specification.
git clone https://noulin.net/git/md4c.git
Log | Files | Refs | README | LICENSE

commit 61f9e2cbedb28e7ab3e56472c1bb02a63226c8d3
parent b86c7f2867855018feda1883a587dd473207372a
Author: Martin Mitas <mity@morous.org>
Date:   Thu, 24 Nov 2016 11:59:59 +0100

Implement block quotes.

Diffstat:
MREADME.md | 2+-
Mmd4c/md4c.c | 66+++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 56 insertions(+), 12 deletions(-)

diff --git a/README.md b/README.md @@ -92,7 +92,7 @@ more or less forms our to do list. - [x] 4.9 Blank lines - **Container Blocks:** - - [ ] 5.1 Block quotes + - [x] 5.1 Block quotes - [ ] 5.2 List items - [ ] 5.3 Lists diff --git a/md4c/md4c.c b/md4c/md4c.c @@ -4442,6 +4442,10 @@ md_line_contains_char(MD_CTX* ctx, OFF beg, CHAR ch, OFF* p_pos) static int md_is_container_compatible(const MD_CONTAINER* pivot, const MD_CONTAINER* container) { + /* Block quote has no "items" like lists. */ + if(container->ch == _T('>')) + return FALSE; + if(container->ch != pivot->ch) return FALSE; if(container->mark_indent > pivot->contents_indent) @@ -4490,6 +4494,10 @@ md_enter_child_containers(MD_CTX* ctx, int n_children) MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, MD_BLOCK_CONTAINER_OPENER)); break; + case _T('>'): + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_QUOTE, MD_BLOCK_CONTAINER_OPENER)); + break; + default: MD_UNREACHABLE(); break; @@ -4514,6 +4522,10 @@ md_leave_child_containers(MD_CTX* ctx, int n_keep) MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_UL, MD_BLOCK_CONTAINER_CLOSER)); break; + case _T('>'): + MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_QUOTE, MD_BLOCK_CONTAINER_CLOSER)); + break; + default: MD_UNREACHABLE(); break; @@ -4531,6 +4543,20 @@ md_is_container_mark(MD_CTX* ctx, unsigned indent, OFF beg, OFF* p_end, MD_CONTA { OFF off = beg; + /* Check for block quote mark. */ + if(off < ctx->size && CH(off) == _T('>')) { + off++; + if(off < ctx->size && CH(off) == _T(' ')) + off++; + p_container->ch = _T('>'); + p_container->is_loose = FALSE; + p_container->mark_indent = indent; + /*p_container->contents_indent = indent+1; Not meaningful*/ + *p_end = off; + return TRUE; + } + + /* Check for list item bullet mark. */ if(off+1 < ctx->size && ISANYOF(off, _T("-+*")) && CH(off+1) == _T(' ')) { p_container->ch = CH(off); p_container->is_loose = FALSE; @@ -4580,12 +4606,27 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end, line->indent = md_line_indentation(ctx, off, &off); line->beg = off; - /* Given the indentation, determine how many of the current containers - * are our parents. */ - while(n_parents < ctx->n_containers && - line->indent >= ctx->containers[n_parents].contents_indent) - { - line->indent -= ctx->containers[n_parents].contents_indent; + /* Given the indentation and block quote marks '>', determine how many of + * the current containers are our parents. */ + while(n_parents < ctx->n_containers) { + MD_CONTAINER* c = &ctx->containers[n_parents]; + + if(c->ch == _T('>') && line->indent < ctx->code_indent_offset && + off < ctx->size && CH(off) == _T('>')) + { + /* Block quote mark. */ + off++; + if(off < ctx->size && CH(off) == _T(' ')) + off++; + line->indent = md_line_indentation(ctx, off, &off); + line->beg = off; + } else if(c->ch != _T('>') && line->indent >= c->contents_indent) { + /* List. */ + line->indent -= c->contents_indent; + } else { + break; + } + n_parents++; } @@ -4674,7 +4715,8 @@ redo: /* Check whether we are Setext underline. */ if(line->indent < ctx->code_indent_offset && pivot_line->type == MD_LINE_TEXT - && (CH(off) == _T('=') || CH(off) == _T('-'))) + && (CH(off) == _T('=') || CH(off) == _T('-')) + && (n_parents == ctx->n_containers)) { unsigned level; @@ -4820,11 +4862,13 @@ done: *p_end = off; - /* If we belong to a list after seeing a blank line, the list is loose. */ + /* If we belong to a list after seeing a blank line, the enclosing is loose. */ if(prev_line_is_blank && line->type != MD_LINE_BLANK && n_parents + n_brothers > 0) { - MD_BLOCK* block = (MD_BLOCK*) (((char*)ctx->block_bytes) + - ctx->containers[n_parents + n_brothers - 1].block_byte_off); - block->flags |= MD_BLOCK_LOOSE_LIST; + MD_CONTAINER* c = &ctx->containers[n_parents + n_brothers - 1]; + if(c->ch != _T('>')) { + MD_BLOCK* block = (MD_BLOCK*) (((char*)ctx->block_bytes) + c->block_byte_off); + block->flags |= MD_BLOCK_LOOSE_LIST; + } } /* Leave any containers we are not part of anymore. */