Propagate to renderer more info about lists (issue #13). Make MD_BLOCK_OL_DETAIL and MD_BLOCK_UL_DETAIL (new structure) expose more info about the lists. In particular flag whether the list is tight or loose, and info about the fundamental chartacter making the list item marks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
diff --git a/md4c/md4c.c b/md4c/md4c.c
index bae422e..965532e 100644
--- a/md4c/md4c.c
+++ b/md4c/md4c.c
@@ -3733,6 +3733,9 @@ struct MD_BLOCK_tag {
*/
unsigned data : 16;
+ /* Leaf blocks: Count of lines (MD_LINE or MD_VERBATIMLINE) on the block.
+ * MD_BLOCK_OL: Start item number.
+ */
unsigned n_lines;
};
@@ -3953,24 +3956,38 @@ md_process_all_blocks(MD_CTX* ctx)
while(byte_off < ctx->n_block_bytes) {
MD_BLOCK* block = (MD_BLOCK*)((char*)ctx->block_bytes + byte_off);
- MD_BLOCK_OL_DETAIL ol_det;
- void* det = NULL;
+ union {
+ MD_BLOCK_UL_DETAIL ul;
+ MD_BLOCK_OL_DETAIL ol;
+ } det;
+
+ switch(block->type) {
+ case MD_BLOCK_UL:
+ det.ul.is_tight = (block->flags & MD_BLOCK_LOOSE_LIST) ? FALSE : TRUE;
+ det.ul.mark = (CHAR) block->data;
+ break;
+
+ case MD_BLOCK_OL:
+ det.ol.start = block->n_lines;
+ det.ol.is_tight = (block->flags & MD_BLOCK_LOOSE_LIST) ? FALSE : TRUE;
+ det.ol.mark_delimiter = (CHAR) block->data;
+ break;
- if(block->type == MD_BLOCK_OL) {
- ol_det.start = block->n_lines;
- det = &ol_det;
+ default:
+ /* noop */
+ break;
}
if(block->flags & MD_BLOCK_CONTAINER) {
if(block->flags & MD_BLOCK_CONTAINER_CLOSER) {
- MD_LEAVE_BLOCK(block->type, det);
+ MD_LEAVE_BLOCK(block->type, &det);
if(block->type == MD_BLOCK_UL || block->type == MD_BLOCK_OL || block->type == MD_BLOCK_QUOTE)
ctx->n_containers--;
}
if(block->flags & MD_BLOCK_CONTAINER_OPENER) {
- MD_ENTER_BLOCK(block->type, det);
+ MD_ENTER_BLOCK(block->type, &det);
if(block->type == MD_BLOCK_UL || block->type == MD_BLOCK_OL) {
ctx->containers[ctx->n_containers].is_loose = (block->flags & MD_BLOCK_LOOSE_LIST);
@@ -4190,7 +4207,8 @@ md_add_line_into_current_block(MD_CTX* ctx, const MD_LINE_ANALYSIS* analysis)
}
static int
-md_push_container_bytes(MD_CTX* ctx, MD_BLOCKTYPE type, unsigned start, unsigned flags)
+md_push_container_bytes(MD_CTX* ctx, MD_BLOCKTYPE type, unsigned start,
+ unsigned data, unsigned flags)
{
MD_BLOCK* block;
int ret = 0;
@@ -4203,7 +4221,7 @@ md_push_container_bytes(MD_CTX* ctx, MD_BLOCKTYPE type, unsigned start, unsigned
block->type = type;
block->flags = flags;
- block->data = 0;
+ block->data = data;
block->n_lines = start;
abort:
@@ -4662,7 +4680,7 @@ md_push_container(MD_CTX* ctx, const MD_CONTAINER* container)
}
static int
-md_enter_child_containers(MD_CTX* ctx, int n_children)
+md_enter_child_containers(MD_CTX* ctx, int n_children, unsigned data)
{
int i;
int ret = 0;
@@ -4687,12 +4705,12 @@ md_enter_child_containers(MD_CTX* ctx, int n_children)
MD_CHECK(md_push_container_bytes(ctx,
(is_ordered_list ? MD_BLOCK_OL : MD_BLOCK_UL),
- c->start, MD_BLOCK_CONTAINER_OPENER));
- MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, 0, MD_BLOCK_CONTAINER_OPENER));
+ c->start, data, MD_BLOCK_CONTAINER_OPENER));
+ MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, 0, data, MD_BLOCK_CONTAINER_OPENER));
break;
case _T('>'):
- MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_QUOTE, 0, MD_BLOCK_CONTAINER_OPENER));
+ MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_QUOTE, 0, data, MD_BLOCK_CONTAINER_OPENER));
break;
default:
@@ -4723,14 +4741,16 @@ md_leave_child_containers(MD_CTX* ctx, int n_keep)
case _T('-'):
case _T('+'):
case _T('*'):
- MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, 0, MD_BLOCK_CONTAINER_CLOSER));
+ MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, 0,
+ 0, MD_BLOCK_CONTAINER_CLOSER));
MD_CHECK(md_push_container_bytes(ctx,
(is_ordered_list ? MD_BLOCK_OL : MD_BLOCK_UL), 0,
- MD_BLOCK_CONTAINER_CLOSER));
+ c->ch, MD_BLOCK_CONTAINER_CLOSER));
break;
case _T('>'):
- MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_QUOTE, 0, MD_BLOCK_CONTAINER_CLOSER));
+ MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_QUOTE, 0,
+ 0, MD_BLOCK_CONTAINER_CLOSER));
break;
default:
@@ -5082,6 +5102,7 @@ redo:
total_indent += line->indent;
line->beg = off;
+ line->data = container.ch;
/* Some of the following whitespace actually still belongs to the mark. */
if(off >= ctx->size || ISNEWLINE(off)) {
@@ -5203,7 +5224,7 @@ done:
*p_end = off;
- /* If we belong to a list after seeing a blank line, the enclosing is loose. */
+ /* If we belong to a list after seeing a blank line, the list is loose. */
if(prev_line_has_list_loosening_effect && line->type != MD_LINE_BLANK && n_parents + n_brothers > 0) {
MD_CONTAINER* c = &ctx->containers[n_parents + n_brothers - 1];
if(c->ch != _T('>')) {
@@ -5219,12 +5240,12 @@ done:
/* Enter any container we found a mark for. */
if(n_brothers > 0) {
MD_ASSERT(n_brothers == 1);
- MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, 0,
+ MD_CHECK(md_push_container_bytes(ctx, MD_BLOCK_LI, 0, 0,
MD_BLOCK_CONTAINER_CLOSER | MD_BLOCK_CONTAINER_OPENER));
}
if(n_children > 0)
- MD_CHECK(md_enter_child_containers(ctx, n_children));
+ MD_CHECK(md_enter_child_containers(ctx, n_children, line->data));
abort:
return ret;
diff --git a/md4c/md4c.h b/md4c/md4c.h
index 1e78647..d2fc60d 100644
--- a/md4c/md4c.h
+++ b/md4c/md4c.h
@@ -62,7 +62,8 @@ enum MD_BLOCKTYPE_tag {
/* <blockquote>...</blockquote> */
MD_BLOCK_QUOTE,
- /* <ul>...</ul> */
+ /* <ul>...</ul>
+ * Detail: Structure MD_BLOCK_UL_DETAIL. */
MD_BLOCK_UL,
/* <ol>...</ol>
@@ -210,10 +211,19 @@ struct MD_ATTRIBUTE_tag {
};
+/* Detailed info for MD_BLOCK_UL_DETAIL. */
+typedef struct MD_BLOCK_UL_DETAIL_tag MD_BLOCK_UL_DETAIL;
+struct MD_BLOCK_UL_DETAIL_tag {
+ int is_tight; /* Non-zero if tight list, zero of loose. */
+ MD_CHAR mark; /* Item bullet character in MarkDown source of the list, e.g. '-', '+', '*'. */
+};
+
/* Detailed info for MD_BLOCK_OL_DETAIL. */
typedef struct MD_BLOCK_OL_DETAIL_tag MD_BLOCK_OL_DETAIL;
struct MD_BLOCK_OL_DETAIL_tag {
unsigned start; /* Start index of the ordered list. */
+ int is_tight; /* Non-zero if tight list, zero of loose. */
+ MD_CHAR mark_delimiter; /* Character delimiting the item marks in MarkDown source, e.g. '.' or ')' */
};
/* Detailed info for MD_BLOCK_H. */