summaryrefslogtreecommitdiff
path: root/src/commonmark.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/commonmark.c')
-rw-r--r--src/commonmark.c87
1 files changed, 59 insertions, 28 deletions
diff --git a/src/commonmark.c b/src/commonmark.c
index c427618..cb30601 100644
--- a/src/commonmark.c
+++ b/src/commonmark.c
@@ -23,6 +23,8 @@
static inline void outc(cmark_renderer *renderer, cmark_escaping escape,
int32_t c, unsigned char nextc) {
bool needs_escaping = false;
+ bool follows_digit = renderer->buffer->size > 0 &&
+ cmark_isdigit(renderer->buffer->ptr[renderer->buffer->size - 1]);
const size_t ENCODED_SIZE = 20;
char encoded[ENCODED_SIZE];
@@ -32,9 +34,12 @@ static inline void outc(cmark_renderer *renderer, cmark_escaping escape,
(c == '*' || c == '_' || c == '[' || c == ']' || c == '#' || c == '<' ||
c == '>' || c == '\\' || c == '`' || c == '!' ||
(c == '&' && isalpha(nextc)) || (c == '!' && nextc == '[') ||
- (renderer->begin_line && (c == '-' || c == '+' || c == '=')) ||
- ((c == '.' || c == ')') &&
- isdigit(renderer->buffer->ptr[renderer->buffer->size - 1])))) ||
+ (renderer->begin_content && (c == '-' || c == '+' || c == '=') &&
+ // begin_content doesn't get set to false til we've passed digits
+ // at the beginning of line, so...
+ !follows_digit) ||
+ (renderer->begin_content && (c == '.' || c == ')') && follows_digit &&
+ (nextc == 0 || cmark_isspace(nextc))))) ||
(escape == URL && (c == '`' || c == '<' || c == '>' || isspace(c) ||
c == '\\' || c == ')' || c == '(')) ||
(escape == TITLE &&
@@ -122,6 +127,9 @@ static bool is_autolink(cmark_node *node) {
}
link_text = node->first_child;
+ if (link_text == NULL) {
+ return false;
+ }
cmark_consolidate_text_nodes(link_text);
realurl = (char *)url->data;
realurllen = url->len;
@@ -136,12 +144,17 @@ static bool is_autolink(cmark_node *node) {
// if node is a block node, returns node.
// otherwise returns first block-level node that is an ancestor of node.
+// if there is no block-level ancestor, returns NULL.
static cmark_node *get_containing_block(cmark_node *node) {
- while (node && (node->type < CMARK_NODE_FIRST_BLOCK ||
- node->type > CMARK_NODE_LAST_BLOCK)) {
- node = node->parent;
+ while (node) {
+ if (node->type >= CMARK_NODE_FIRST_BLOCK &&
+ node->type <= CMARK_NODE_LAST_BLOCK) {
+ return node;
+ } else {
+ node = node->parent;
+ }
}
- return node;
+ return NULL;
}
static int S_render_node(cmark_renderer *renderer, cmark_node *node,
@@ -165,10 +178,11 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
if (!(node->type == CMARK_NODE_ITEM && node->prev == NULL && entering)) {
tmp = get_containing_block(node);
renderer->in_tight_list_item =
- (tmp->type == CMARK_NODE_ITEM &&
- cmark_node_get_list_tight(tmp->parent)) ||
- (tmp && tmp->parent && tmp->parent->type == CMARK_NODE_ITEM &&
- cmark_node_get_list_tight(tmp->parent->parent));
+ tmp && // tmp might be NULL if there is no containing block
+ ((tmp->type == CMARK_NODE_ITEM &&
+ cmark_node_get_list_tight(tmp->parent)) ||
+ (tmp && tmp->parent && tmp->parent->type == CMARK_NODE_ITEM &&
+ cmark_node_get_list_tight(tmp->parent->parent)));
}
switch (node->type) {
@@ -178,6 +192,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
case CMARK_NODE_BLOCK_QUOTE:
if (entering) {
LIT("> ");
+ renderer->begin_content = true;
cmark_strbuf_puts(renderer->prefix, "> ");
} else {
cmark_strbuf_truncate(renderer->prefix, renderer->prefix->size - 2);
@@ -188,15 +203,17 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
case CMARK_NODE_LIST:
if (!entering && node->next && (node->next->type == CMARK_NODE_CODE_BLOCK ||
node->next->type == CMARK_NODE_LIST)) {
- // this ensures 2 blank lines after list,
- // if before code block or list:
- LIT("\n");
+ // this ensures that a following code block or list will be
+ // inteprereted correctly.
+ CR();
+ LIT("<!-- end list -->");
+ BLANKLINE();
}
break;
case CMARK_NODE_ITEM:
if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
- marker_width = 2;
+ marker_width = 4;
} else {
list_number = cmark_node_get_list_start(node->parent);
list_delim = cmark_node_get_list_delim(node->parent);
@@ -215,13 +232,14 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
}
if (entering) {
if (cmark_node_get_list_type(node->parent) == CMARK_BULLET_LIST) {
- LIT("* ");
- cmark_strbuf_puts(renderer->prefix, " ");
+ LIT(" - ");
+ renderer->begin_content = true;
} else {
LIT(listmarker);
- for (i = marker_width; i--;) {
- cmark_strbuf_putc(renderer->prefix, ' ');
- }
+ renderer->begin_content = true;
+ }
+ for (i = marker_width; i--;) {
+ cmark_strbuf_putc(renderer->prefix, ' ');
}
} else {
cmark_strbuf_truncate(renderer->prefix,
@@ -230,12 +248,13 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
}
break;
- case CMARK_NODE_HEADER:
+ case CMARK_NODE_HEADING:
if (entering) {
- for (int i = cmark_node_get_header_level(node); i > 0; i--) {
+ for (i = cmark_node_get_heading_level(node); i > 0; i--) {
LIT("#");
}
LIT(" ");
+ renderer->begin_content = true;
renderer->no_wrap = true;
} else {
renderer->no_wrap = false;
@@ -281,13 +300,20 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
BLANKLINE();
break;
- case CMARK_NODE_HTML:
+ case CMARK_NODE_HTML_BLOCK:
BLANKLINE();
OUT(cmark_node_get_literal(node), false, LITERAL);
BLANKLINE();
break;
- case CMARK_NODE_HRULE:
+ case CMARK_NODE_CUSTOM_BLOCK:
+ BLANKLINE();
+ OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
+ false, LITERAL);
+ BLANKLINE();
+ break;
+
+ case CMARK_NODE_THEMATIC_BREAK:
BLANKLINE();
LIT("-----");
BLANKLINE();
@@ -305,7 +331,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
case CMARK_NODE_LINEBREAK:
if (!(CMARK_OPT_HARDBREAKS & options)) {
- LIT("\\");
+ LIT(" ");
}
CR();
break;
@@ -337,10 +363,15 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
}
break;
- case CMARK_NODE_INLINE_HTML:
+ case CMARK_NODE_HTML_INLINE:
OUT(cmark_node_get_literal(node), false, LITERAL);
break;
+ case CMARK_NODE_CUSTOM_INLINE:
+ OUT(entering ? cmark_node_get_on_enter(node) : cmark_node_get_on_exit(node),
+ false, LITERAL);
+ break;
+
case CMARK_NODE_STRONG:
if (entering) {
LIT("**");
@@ -370,9 +401,9 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
if (entering) {
LIT("<");
if (strncmp(cmark_node_get_url(node), "mailto:", 7) == 0) {
- LIT((char *)cmark_node_get_url(node) + 7);
+ LIT((const char *)cmark_node_get_url(node) + 7);
} else {
- LIT((char *)cmark_node_get_url(node));
+ LIT((const char *)cmark_node_get_url(node));
}
LIT(">");
// return signal to skip contents of node...