Upgrade md4c to 0.4.7

Change-Id: I9400c2df13c30fb0bc14728a0c44851c2d1e9079
Pick-to: 6.0 5.15
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
Giuseppe D'Angelo 2020-12-27 22:45:09 +01:00
parent 1b4d70676c
commit 1f4434a8e2
4 changed files with 131 additions and 86 deletions

View File

@ -1,7 +1,7 @@
# The MIT License (MIT) # The MIT License (MIT)
Copyright © 2016-2019 Martin Mitáš Copyright © 2016-2020 Martin Mitáš
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the “Software”), copy of this software and associated documentation files (the “Software”),

View File

@ -72,6 +72,48 @@
#define FALSE 0 #define FALSE 0
#endif #endif
#define MD_LOG(msg) \
do { \
if(ctx->parser.debug_log != NULL) \
ctx->parser.debug_log((msg), ctx->userdata); \
} while(0)
#ifdef DEBUG
#define MD_ASSERT(cond) \
do { \
if(!(cond)) { \
MD_LOG(__FILE__ ":" STRINGIZE(__LINE__) ": " \
"Assertion '" STRINGIZE(cond) "' failed."); \
exit(1); \
} \
} while(0)
#define MD_UNREACHABLE() MD_ASSERT(1 == 0)
#else
#ifdef __GNUC__
#define MD_ASSERT(cond) do { if(!(cond)) __builtin_unreachable(); } while(0)
#define MD_UNREACHABLE() do { __builtin_unreachable(); } while(0)
#elif defined _MSC_VER && _MSC_VER > 120
#define MD_ASSERT(cond) do { __assume(cond); } while(0)
#define MD_UNREACHABLE() do { __assume(0); } while(0)
#else
#define MD_ASSERT(cond) do {} while(0)
#define MD_UNREACHABLE() do {} while(0)
#endif
#endif
/* For falling through case labels in switch statements. */
#if defined __clang__ && __clang_major__ >= 12
#define MD_FALLTHROUGH() __attribute__((fallthrough))
#elif defined __GNUC__ && __GNUC__ >= 7
#define MD_FALLTHROUGH() __attribute__((fallthrough))
#else
#define MD_FALLTHROUGH() ((void)0)
#endif
/* Suppress "unused parameter" warnings. */
#define MD_UNUSED(x) ((void)x)
/************************ /************************
*** Internal Types *** *** Internal Types ***
@ -230,41 +272,6 @@ struct MD_VERBATIMLINE_tag {
}; };
/*******************
*** Debugging ***
*******************/
#define MD_LOG(msg) \
do { \
if(ctx->parser.debug_log != NULL) \
ctx->parser.debug_log((msg), ctx->userdata); \
} while(0)
#ifdef DEBUG
#define MD_ASSERT(cond) \
do { \
if(!(cond)) { \
MD_LOG(__FILE__ ":" STRINGIZE(__LINE__) ": " \
"Assertion '" STRINGIZE(cond) "' failed."); \
exit(1); \
} \
} while(0)
#define MD_UNREACHABLE() MD_ASSERT(1 == 0)
#else
#ifdef __GNUC__
#define MD_ASSERT(cond) do { if(!(cond)) __builtin_unreachable(); } while(0)
#define MD_UNREACHABLE() do { __builtin_unreachable(); } while(0)
#elif defined _MSC_VER && _MSC_VER > 120
#define MD_ASSERT(cond) do { __assume(cond); } while(0)
#define MD_UNREACHABLE() do { __assume(0); } while(0)
#else
#define MD_ASSERT(cond) do {} while(0)
#define MD_UNREACHABLE() do {} while(0)
#endif
#endif
/***************** /*****************
*** Helpers *** *** Helpers ***
*****************/ *****************/
@ -466,7 +473,7 @@ md_text_with_null_replacement(MD_CTX* ctx, MD_TEXTTYPE type, const CHAR* str, SZ
typedef struct MD_UNICODE_FOLD_INFO_tag MD_UNICODE_FOLD_INFO; typedef struct MD_UNICODE_FOLD_INFO_tag MD_UNICODE_FOLD_INFO;
struct MD_UNICODE_FOLD_INFO_tag { struct MD_UNICODE_FOLD_INFO_tag {
unsigned codepoints[3]; unsigned codepoints[3];
int n_codepoints; unsigned n_codepoints;
}; };
@ -670,7 +677,7 @@ struct MD_UNICODE_FOLD_INFO_tag {
const unsigned* map; const unsigned* map;
const unsigned* data; const unsigned* data;
size_t map_size; size_t map_size;
int n_codepoints; unsigned n_codepoints;
} FOLD_MAP_LIST[] = { } FOLD_MAP_LIST[] = {
{ FOLD_MAP_1, FOLD_MAP_1_DATA, SIZEOF_ARRAY(FOLD_MAP_1), 1 }, { FOLD_MAP_1, FOLD_MAP_1_DATA, SIZEOF_ARRAY(FOLD_MAP_1), 1 },
{ FOLD_MAP_2, FOLD_MAP_2_DATA, SIZEOF_ARRAY(FOLD_MAP_2), 2 }, { FOLD_MAP_2, FOLD_MAP_2_DATA, SIZEOF_ARRAY(FOLD_MAP_2), 2 },
@ -695,7 +702,7 @@ struct MD_UNICODE_FOLD_INFO_tag {
index = md_unicode_bsearch__(codepoint, FOLD_MAP_LIST[i].map, FOLD_MAP_LIST[i].map_size); index = md_unicode_bsearch__(codepoint, FOLD_MAP_LIST[i].map, FOLD_MAP_LIST[i].map_size);
if(index >= 0) { if(index >= 0) {
/* Found the mapping. */ /* Found the mapping. */
int n_codepoints = FOLD_MAP_LIST[i].n_codepoints; unsigned n_codepoints = FOLD_MAP_LIST[i].n_codepoints;
const unsigned* map = FOLD_MAP_LIST[i].map; const unsigned* map = FOLD_MAP_LIST[i].map;
const unsigned* codepoints = FOLD_MAP_LIST[i].data + (index * n_codepoints); const unsigned* codepoints = FOLD_MAP_LIST[i].data + (index * n_codepoints);
@ -894,6 +901,8 @@ md_merge_lines(MD_CTX* ctx, OFF beg, OFF end, const MD_LINE* lines, int n_lines,
int line_index = 0; int line_index = 0;
OFF off = beg; OFF off = beg;
MD_UNUSED(n_lines);
while(1) { while(1) {
const MD_LINE* line = &lines[line_index]; const MD_LINE* line = &lines[line_index];
OFF line_end = line->end; OFF line_end = line->end;
@ -1235,6 +1244,7 @@ static int
md_is_hex_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end) md_is_hex_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end)
{ {
OFF off = beg; OFF off = beg;
MD_UNUSED(ctx);
while(off < max_end && ISXDIGIT_(text[off]) && off - beg <= 8) while(off < max_end && ISXDIGIT_(text[off]) && off - beg <= 8)
off++; off++;
@ -1251,6 +1261,7 @@ static int
md_is_dec_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end) md_is_dec_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end)
{ {
OFF off = beg; OFF off = beg;
MD_UNUSED(ctx);
while(off < max_end && ISDIGIT_(text[off]) && off - beg <= 8) while(off < max_end && ISDIGIT_(text[off]) && off - beg <= 8)
off++; off++;
@ -1267,6 +1278,7 @@ static int
md_is_named_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end) md_is_named_entity_contents(MD_CTX* ctx, const CHAR* text, OFF beg, OFF max_end, OFF* p_end)
{ {
OFF off = beg; OFF off = beg;
MD_UNUSED(ctx);
if(off < max_end && ISALPHA_(text[off])) if(off < max_end && ISALPHA_(text[off]))
off++; off++;
@ -1372,6 +1384,8 @@ md_build_attr_append_substr(MD_CTX* ctx, MD_ATTRIBUTE_BUILD* build,
static void static void
md_free_attribute(MD_CTX* ctx, MD_ATTRIBUTE_BUILD* build) md_free_attribute(MD_CTX* ctx, MD_ATTRIBUTE_BUILD* build)
{ {
MD_UNUSED(ctx);
if(build->substr_alloc > 0) { if(build->substr_alloc > 0) {
free(build->text); free(build->text);
free(build->substr_types); free(build->substr_types);
@ -1547,12 +1561,6 @@ md_link_label_cmp_load_fold_info(const CHAR* label, OFF off, SZ size,
goto whitespace; goto whitespace;
} }
if(ISNEWLINE_(label[off])) {
/* Treat new lines as a whitespace. */
off++;
goto whitespace;
}
codepoint = md_decode_unicode(label, off, size, &char_size); codepoint = md_decode_unicode(label, off, size, &char_size);
off += char_size; off += char_size;
if(ISUNICODEWHITESPACE_(codepoint)) { if(ISUNICODEWHITESPACE_(codepoint)) {
@ -1575,8 +1583,6 @@ md_link_label_cmp(const CHAR* a_label, SZ a_size, const CHAR* b_label, SZ b_size
{ {
OFF a_off; OFF a_off;
OFF b_off; OFF b_off;
int a_reached_end = FALSE;
int b_reached_end = FALSE;
MD_UNICODE_FOLD_INFO a_fi = { { 0 }, 0 }; MD_UNICODE_FOLD_INFO a_fi = { { 0 }, 0 };
MD_UNICODE_FOLD_INFO b_fi = { { 0 }, 0 }; MD_UNICODE_FOLD_INFO b_fi = { { 0 }, 0 };
OFF a_fi_off = 0; OFF a_fi_off = 0;
@ -1585,17 +1591,17 @@ md_link_label_cmp(const CHAR* a_label, SZ a_size, const CHAR* b_label, SZ b_size
a_off = md_skip_unicode_whitespace(a_label, 0, a_size); a_off = md_skip_unicode_whitespace(a_label, 0, a_size);
b_off = md_skip_unicode_whitespace(b_label, 0, b_size); b_off = md_skip_unicode_whitespace(b_label, 0, b_size);
while(!a_reached_end || !b_reached_end) { while(a_off < a_size || a_fi_off < a_fi.n_codepoints ||
b_off < b_size || b_fi_off < b_fi.n_codepoints)
{
/* If needed, load fold info for next char. */ /* If needed, load fold info for next char. */
if(a_fi_off >= a_fi.n_codepoints) { if(a_fi_off >= a_fi.n_codepoints) {
a_fi_off = 0; a_fi_off = 0;
a_off = md_link_label_cmp_load_fold_info(a_label, a_off, a_size, &a_fi); a_off = md_link_label_cmp_load_fold_info(a_label, a_off, a_size, &a_fi);
a_reached_end = (a_off >= a_size);
} }
if(b_fi_off >= b_fi.n_codepoints) { if(b_fi_off >= b_fi.n_codepoints) {
b_fi_off = 0; b_fi_off = 0;
b_off = md_link_label_cmp_load_fold_info(b_label, b_off, b_size, &b_fi); b_off = md_link_label_cmp_load_fold_info(b_label, b_off, b_size, &b_fi);
b_reached_end = (b_off >= b_size);
} }
cmp = b_fi.codepoints[b_fi_off] - a_fi.codepoints[a_fi_off]; cmp = b_fi.codepoints[b_fi_off] - a_fi.codepoints[a_fi_off];
@ -2671,7 +2677,7 @@ md_rollback(MD_CTX* ctx, int opener_index, int closer_index, int how)
mark_index = mark->prev; mark_index = mark->prev;
break; break;
} }
/* Pass through. */ MD_FALLTHROUGH();
default: default:
mark_index--; mark_index--;
break; break;
@ -3227,7 +3233,7 @@ md_collect_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines, int table_mode)
/* Push a dummy as a reserve for a closer. */ /* Push a dummy as a reserve for a closer. */
PUSH_MARK('D', off, off, 0); PUSH_MARK('D', off, off, 0);
off += 1 + suffix_size; off += 1 + suffix_size;
continue; break;
} }
} }
@ -3524,6 +3530,10 @@ md_resolve_links(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
if(is_link) { if(is_link) {
/* Eat the 2nd "[...]". */ /* Eat the 2nd "[...]". */
closer->end = next_closer->end; closer->end = next_closer->end;
/* Do not analyze the label as a standalone link in the next
* iteration. */
next_index = ctx->marks[next_index].prev;
} }
} else { } else {
if(closer->end < ctx->size && CH(closer->end) == _T('(')) { if(closer->end < ctx->size && CH(closer->end) == _T('(')) {
@ -3679,7 +3689,7 @@ md_analyze_emph(MD_CTX* ctx, int mark_index)
/* If we can be a closer, try to resolve with the preceding opener. */ /* If we can be a closer, try to resolve with the preceding opener. */
if(mark->flags & MD_MARK_POTENTIAL_CLOSER) { if(mark->flags & MD_MARK_POTENTIAL_CLOSER) {
MD_MARK* opener = NULL; MD_MARK* opener = NULL;
int opener_index; int opener_index = 0;
if(mark->ch == _T('*')) { if(mark->ch == _T('*')) {
MD_MARKCHAIN* opener_chains[6]; MD_MARKCHAIN* opener_chains[6];
@ -3806,6 +3816,7 @@ md_analyze_permissive_url_autolink(MD_CTX* ctx, int mark_index)
int has_underscore_in_last_seg = FALSE; int has_underscore_in_last_seg = FALSE;
int has_underscore_in_next_to_last_seg = FALSE; int has_underscore_in_next_to_last_seg = FALSE;
int n_opened_parenthesis = 0; int n_opened_parenthesis = 0;
int n_excess_parenthesis = 0;
/* Check for domain. */ /* Check for domain. */
while(off < ctx->size) { while(off < ctx->size) {
@ -3844,17 +3855,28 @@ md_analyze_permissive_url_autolink(MD_CTX* ctx, int mark_index)
if(n_opened_parenthesis > 0) if(n_opened_parenthesis > 0)
n_opened_parenthesis--; n_opened_parenthesis--;
else else
break; n_excess_parenthesis++;
} }
off++; off++;
} }
/* These cannot be last char In such case they are more likely normal
* punctuation. */
if(ISANYOF(off-1, _T("?!.,:*_~")))
off--;
/* Ok. Lets call it auto-link. Adapt opener and create closer to zero /* Trim a trailing punctuation from the end. */
while(TRUE) {
if(ISANYOF(off-1, _T("?!.,:*_~"))) {
off--;
} else if(CH(off-1) == ')' && n_excess_parenthesis > 0) {
/* Unmatched ')' can be in an interior of the path but not at the
* of it, so the auto-link may be safely nested in a parenthesis
* pair. */
off--;
n_excess_parenthesis--;
} else {
break;
}
}
/* Ok. Lets call it an auto-link. Adapt opener and create closer to zero
* length so all the contents becomes the link text. */ * length so all the contents becomes the link text. */
MD_ASSERT(closer->ch == 'D'); MD_ASSERT(closer->ch == 'D');
opener->end = opener->beg; opener->end = opener->beg;
@ -3918,6 +3940,8 @@ md_analyze_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines,
int mark_beg, int mark_end, const CHAR* mark_chars) int mark_beg, int mark_end, const CHAR* mark_chars)
{ {
int i = mark_beg; int i = mark_beg;
MD_UNUSED(lines);
MD_UNUSED(n_lines);
while(i < mark_end) { while(i < mark_end) {
MD_MARK* mark = &ctx->marks[i]; MD_MARK* mark = &ctx->marks[i];
@ -4136,7 +4160,7 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
} }
break; break;
} }
/* Fall though. */ MD_FALLTHROUGH();
case '*': /* Emphasis, strong emphasis. */ case '*': /* Emphasis, strong emphasis. */
if(mark->flags & MD_MARK_OPENER) { if(mark->flags & MD_MARK_OPENER) {
@ -4235,6 +4259,7 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
break; break;
} }
/* Pass through, if auto-link. */ /* Pass through, if auto-link. */
MD_FALLTHROUGH();
case '@': /* Permissive e-mail autolink. */ case '@': /* Permissive e-mail autolink. */
case ':': /* Permissive URL autolink. */ case ':': /* Permissive URL autolink. */
@ -4491,12 +4516,14 @@ md_process_table_block_contents(MD_CTX* ctx, int col_count, const MD_LINE* lines
lines[0].beg, lines[0].end, align, col_count)); lines[0].beg, lines[0].end, align, col_count));
MD_LEAVE_BLOCK(MD_BLOCK_THEAD, NULL); MD_LEAVE_BLOCK(MD_BLOCK_THEAD, NULL);
if(n_lines > 2) {
MD_ENTER_BLOCK(MD_BLOCK_TBODY, NULL); MD_ENTER_BLOCK(MD_BLOCK_TBODY, NULL);
for(i = 2; i < n_lines; i++) { for(i = 2; i < n_lines; i++) {
MD_CHECK(md_process_table_row(ctx, MD_BLOCK_TD, MD_CHECK(md_process_table_row(ctx, MD_BLOCK_TD,
lines[i].beg, lines[i].end, align, col_count)); lines[i].beg, lines[i].end, align, col_count));
} }
MD_LEAVE_BLOCK(MD_BLOCK_TBODY, NULL); MD_LEAVE_BLOCK(MD_BLOCK_TBODY, NULL);
}
abort: abort:
free(align); free(align);
@ -4665,6 +4692,7 @@ md_process_leaf_block(MD_CTX* ctx, const MD_BLOCK* block)
union { union {
MD_BLOCK_H_DETAIL header; MD_BLOCK_H_DETAIL header;
MD_BLOCK_CODE_DETAIL code; MD_BLOCK_CODE_DETAIL code;
MD_BLOCK_TABLE_DETAIL table;
} det; } det;
MD_ATTRIBUTE_BUILD info_build; MD_ATTRIBUTE_BUILD info_build;
MD_ATTRIBUTE_BUILD lang_build; MD_ATTRIBUTE_BUILD lang_build;
@ -4693,6 +4721,12 @@ md_process_leaf_block(MD_CTX* ctx, const MD_BLOCK* block)
} }
break; break;
case MD_BLOCK_TABLE:
det.table.col_count = block->data;
det.table.head_row_count = 1;
det.table.body_row_count = block->n_lines - 2;
break;
default: default:
/* Noop. */ /* Noop. */
break; break;
@ -5504,7 +5538,7 @@ md_enter_child_containers(MD_CTX* ctx, int n_children, unsigned data)
case _T(')'): case _T(')'):
case _T('.'): case _T('.'):
is_ordered_list = TRUE; is_ordered_list = TRUE;
/* Pass through */ MD_FALLTHROUGH();
case _T('-'): case _T('-'):
case _T('+'): case _T('+'):
@ -5550,7 +5584,7 @@ md_leave_child_containers(MD_CTX* ctx, int n_keep)
case _T(')'): case _T(')'):
case _T('.'): case _T('.'):
is_ordered_list = TRUE; is_ordered_list = TRUE;
/* Pass through */ MD_FALLTHROUGH();
case _T('-'): case _T('-'):
case _T('+'): case _T('+'):
@ -5586,11 +5620,11 @@ md_is_container_mark(MD_CTX* ctx, unsigned indent, OFF beg, OFF* p_end, MD_CONTA
OFF off = beg; OFF off = beg;
OFF max_end; OFF max_end;
if(indent >= ctx->code_indent_offset) if(off >= ctx->size || indent >= ctx->code_indent_offset)
return FALSE; return FALSE;
/* Check for block quote mark. */ /* Check for block quote mark. */
if(off < ctx->size && CH(off) == _T('>')) { if(CH(off) == _T('>')) {
off++; off++;
p_container->ch = _T('>'); p_container->ch = _T('>');
p_container->is_loose = FALSE; p_container->is_loose = FALSE;
@ -5602,7 +5636,7 @@ md_is_container_mark(MD_CTX* ctx, unsigned indent, OFF beg, OFF* p_end, MD_CONTA
} }
/* Check for list item bullet mark. */ /* Check for list item bullet mark. */
if(off+1 < ctx->size && ISANYOF(off, _T("-+*")) && (ISBLANK(off+1) || ISNEWLINE(off+1))) { if(ISANYOF(off, _T("-+*")) && (off+1 >= ctx->size || ISBLANK(off+1) || ISNEWLINE(off+1))) {
p_container->ch = CH(off); p_container->ch = CH(off);
p_container->is_loose = FALSE; p_container->is_loose = FALSE;
p_container->is_task = FALSE; p_container->is_task = FALSE;
@ -5621,9 +5655,9 @@ md_is_container_mark(MD_CTX* ctx, unsigned indent, OFF beg, OFF* p_end, MD_CONTA
p_container->start = p_container->start * 10 + CH(off) - _T('0'); p_container->start = p_container->start * 10 + CH(off) - _T('0');
off++; off++;
} }
if(off > beg && off+1 < ctx->size && if(off > beg &&
(CH(off) == _T('.') || CH(off) == _T(')')) && (CH(off) == _T('.') || CH(off) == _T(')')) &&
(ISBLANK(off+1) || ISNEWLINE(off+1))) (off+1 >= ctx->size || ISBLANK(off+1) || ISNEWLINE(off+1)))
{ {
p_container->ch = CH(off); p_container->ch = CH(off);
p_container->is_loose = FALSE; p_container->is_loose = FALSE;
@ -5655,7 +5689,7 @@ md_line_indentation(MD_CTX* ctx, unsigned total_indent, OFF beg, OFF* p_end)
return indent - total_indent; return indent - total_indent;
} }
static const MD_LINE_ANALYSIS md_dummy_blank_line = { MD_LINE_BLANK, 0 }; static const MD_LINE_ANALYSIS md_dummy_blank_line = { MD_LINE_BLANK, 0, 0, 0, 0 };
/* Analyze type of the line and find some its properties. This serves as a /* Analyze type of the line and find some its properties. This serves as a
* main input for determining type and boundaries of a block. */ * main input for determining type and boundaries of a block. */
@ -5786,12 +5820,14 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end,
#if 1 #if 1
/* See https://github.com/mity/md4c/issues/6 /* See https://github.com/mity/md4c/issues/6
* *
* This ugly checking tests we are in (yet empty) list item but not * This ugly checking tests we are in (yet empty) list item but
* its very first line (with the list item mark). * not its very first line (i.e. not the line with the list
* item mark).
* *
* If we are such blank line, then any following non-blank line * If we are such a blank line, then any following non-blank
* which would be part of this list item actually ends the list * line which would be part of the list item actually has to
* because "a list item can begin with at most one blank line." * end the list because according to the specification, "a list
* item can begin with at most one blank line."
*/ */
if(n_parents > 0 && ctx->containers[n_parents-1].ch != _T('>') && if(n_parents > 0 && ctx->containers[n_parents-1].ch != _T('>') &&
n_brothers + n_children == 0 && ctx->current_block == NULL && n_brothers + n_children == 0 && ctx->current_block == NULL &&
@ -5806,9 +5842,10 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end,
break; break;
} else { } else {
#if 1 #if 1
/* This is 2nd half of the hack. If the flag is set (that is there /* This is the 2nd half of the hack. If the flag is set (i.e. there
* were 2nd blank line at the start of the list item) and we would also * was a 2nd blank line at the beginning of the list item) and if
* belonging to such list item, than interrupt the list. */ * we would otherwise still belong to the list item, we enforce
* the end of the list. */
ctx->last_line_has_list_loosening_effect = FALSE; ctx->last_line_has_list_loosening_effect = FALSE;
if(ctx->last_list_item_starts_with_two_blank_lines) { if(ctx->last_list_item_starts_with_two_blank_lines) {
if(n_parents > 0 && ctx->containers[n_parents-1].ch != _T('>') && if(n_parents > 0 && ctx->containers[n_parents-1].ch != _T('>') &&

View File

@ -91,7 +91,8 @@ typedef enum MD_BLOCKTYPE {
MD_BLOCK_P, MD_BLOCK_P,
/* <table>...</table> and its contents. /* <table>...</table> and its contents.
* Detail: Structure MD_BLOCK_TD_DETAIL (used with MD_BLOCK_TH and MD_BLOCK_TD) * Detail: Structure MD_BLOCK_TABLE_DETAIL (for MD_BLOCK_TABLE),
* structure MD_BLOCK_TD_DETAIL (for MD_BLOCK_TH and MD_BLOCK_TD)
* Note all of these are used only if extension MD_FLAG_TABLES is enabled. */ * Note all of these are used only if extension MD_FLAG_TABLES is enabled. */
MD_BLOCK_TABLE, MD_BLOCK_TABLE,
MD_BLOCK_THEAD, MD_BLOCK_THEAD,
@ -267,6 +268,13 @@ typedef struct MD_BLOCK_CODE_DETAIL {
MD_CHAR fence_char; /* The character used for fenced code block; or zero for indented code block. */ MD_CHAR fence_char; /* The character used for fenced code block; or zero for indented code block. */
} MD_BLOCK_CODE_DETAIL; } MD_BLOCK_CODE_DETAIL;
/* Detailed info for MD_BLOCK_TABLE. */
typedef struct MD_BLOCK_TABLE_DETAIL {
unsigned col_count; /* Count of columns in the table. */
unsigned head_row_count; /* Count of rows in the table header (currently always 1) */
unsigned body_row_count; /* Count of rows in the table body */
} MD_BLOCK_TABLE_DETAIL;
/* Detailed info for MD_BLOCK_TH and MD_BLOCK_TD. */ /* Detailed info for MD_BLOCK_TH and MD_BLOCK_TD. */
typedef struct MD_BLOCK_TD_DETAIL { typedef struct MD_BLOCK_TD_DETAIL {
MD_ALIGN align; MD_ALIGN align;

View File

@ -9,7 +9,7 @@
"License": "MIT License", "License": "MIT License",
"LicenseId": "MIT", "LicenseId": "MIT",
"LicenseFile": "LICENSE.md", "LicenseFile": "LICENSE.md",
"Version": "0.4.6", "Version": "0.4.7",
"DownloadLocation": "https://github.com/mity/md4c/releases/tag/release-0.4.6", "DownloadLocation": "https://github.com/mity/md4c/releases/tag/release-0.4.7",
"Copyright": "Copyright © 2016-2020 Martin Mitáš" "Copyright": "Copyright © 2016-2020 Martin Mitáš"
} }