From 1cf1ec9a8f893a41910a300d9d8f1e6c20288287 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer ");
+ }
+ break;
+
+ case NODE_BQUOTE:
+ cr(html);
+ strbuf_puts(html, " ");
- inlines_to_html(html, b->first_child);
- strbuf_puts(html, "\n");
+ // BQUOTE doesn't use any of the 'as' structs,
+ // so the 'list' member can be used to store the
+ // current value of 'tight'.
+ cur->as.list.tight = tight;
+ tight = false;
+ break;
+
+ case NODE_LIST_ITEM:
+ cr(html);
+ strbuf_puts(html, "
\n");
+ }
+ else if (list->start == 1) {
+ strbuf_puts(html, "
\n");
+ }
+ else {
+ strbuf_printf(html, "
\n",
+ list->start);
+ }
+
+ // Store the current value of 'tight' by swapping.
+ tmp = list->tight;
+ list->tight = tight;
+ tight = tmp;
+ break;
+ }
+
+ case NODE_ATX_HEADER:
+ case NODE_SETEXT_HEADER:
+ cr(html);
+ start_header[2] = '0' + cur->as.header.level;
+ strbuf_puts(html, start_header);
+ break;
+
+ case NODE_INDENTED_CODE:
+ case NODE_FENCED_CODE: {
+ strbuf *info = &cur->as.code.info;
+ cr(html);
+
+ if (cur->type != NODE_FENCED_CODE
+ || strbuf_len(info) == 0) {
+ strbuf_puts(html, "
");
+ }
+ else {
+ int first_tag = strbuf_strchr(info, ' ', 0);
+ if (first_tag < 0)
+ first_tag = strbuf_len(info);
+
+ strbuf_puts(html,
+ "
ptr, first_tag);
+ strbuf_puts(html, "\">");
+ }
+
+ escape_html(html, cur->string_content.ptr, cur->string_content.size);
+ break;
+ }
+
+ case NODE_HTML:
+ strbuf_put(html, cur->string_content.ptr, cur->string_content.size);
+ break;
+
+ case NODE_HRULE:
+ strbuf_puts(html, "
\n");
+ break;
+
+ case NODE_REFERENCE_DEF:
+ break;
+
case NODE_STRING:
- escape_html(html, ils->as.literal.data, ils->as.literal.len);
+ escape_html(html, cur->as.literal.data, cur->as.literal.len);
break;
case NODE_LINEBREAK:
@@ -153,217 +205,154 @@ static void inlines_to_html(strbuf *html, cmark_node* ils)
case NODE_INLINE_CODE:
strbuf_puts(html, "");
- escape_html(html, ils->as.literal.data, ils->as.literal.len);
- strbuf_puts(html, "
");
+ escape_html(html, cur->as.literal.data, cur->as.literal.len);
break;
case NODE_INLINE_HTML:
strbuf_put(html,
- ils->as.literal.data,
- ils->as.literal.len);
+ cur->as.literal.data,
+ cur->as.literal.len);
break;
case NODE_LINK:
strbuf_puts(html, "as.link.url)
- escape_href(html, ils->as.link.url, -1);
+ if (cur->as.link.url)
+ escape_href(html, cur->as.link.url, -1);
- if (ils->as.link.title) {
+ if (cur->as.link.title) {
strbuf_puts(html, "\" title=\"");
- escape_html(html, ils->as.link.title, -1);
+ escape_html(html, cur->as.link.title, -1);
}
strbuf_puts(html, "\">");
- visit_children = true;
- rstack = push_render_stack(rstack, ils->next, "");
break;
case NODE_IMAGE:
strbuf_puts(html, "as.link.url)
- escape_href(html, ils->as.link.url, -1);
+ if (cur->as.link.url)
+ escape_href(html, cur->as.link.url, -1);
strbuf_puts(html, "\" alt=\"");
- inlines_to_plain_html(html, ils->first_child);
+ inlines_to_plain_html(html, cur);
- if (ils->as.link.title) {
+ if (cur->as.link.title) {
strbuf_puts(html, "\" title=\"");
- escape_html(html, ils->as.link.title, -1);
+ escape_html(html, cur->as.link.title, -1);
}
strbuf_puts(html, "\" />");
+ visit_children = false;
break;
case NODE_STRONG:
strbuf_puts(html, "");
- visit_children = true;
- rstack = push_render_stack(rstack, ils->next, "");
break;
case NODE_EMPH:
strbuf_puts(html, "");
- visit_children = true;
- rstack = push_render_stack(rstack, ils->next, "");
break;
+
default:
- break;
+ assert(false);
}
- if (visit_children) {
- ils = ils->first_child;
- } else {
- ils = ils->next;
+
+ if (visit_children && cur->first_child) {
+ cur = cur->first_child;
+ continue;
+ }
+
+ next_sibling:
+ tight = finish_node(html, cur, tight);
+ if (cur == node) {
+ break;
}
- while (ils == NULL && rstack != NULL) {
- strbuf_puts(html, rstack->literal);
- ils = rstack->next_sibling;
- rstack = pop_render_stack(rstack);
+ if (cur->next) {
+ cur = cur->next;
+ continue;
}
+ cur = cur->parent;
+ goto next_sibling;
}
-
- free_render_stack(rstack);
}
-// Convert a cmark_node list to HTML. Returns 0 on success, and sets result.
-static void blocks_to_html(strbuf *html, cmark_node *b)
+// Returns the restored value of 'tight'.
+static bool
+finish_node(strbuf *html, cmark_node *node, bool tight)
{
- cmark_list *data;
- render_stack* rstack = NULL;
- bool visit_children = false;
- bool tight = false;
-
- while(b != NULL) {
- visit_children = false;
- switch(b->type) {
- case NODE_DOCUMENT:
- rstack = push_render_stack(rstack, b->next, "");
- rstack->tight = false;
- rstack->trim = false;
- visit_children = true;
- break;
-
- case NODE_PARAGRAPH:
- if (tight) {
- inlines_to_html(html, b->first_child);
- } else {
- cr(html);
- strbuf_puts(html, "
\n");
- rstack = push_render_stack(rstack, b->next, "
\n");
- rstack->tight = tight;
- rstack->trim = false;
- tight = false;
- visit_children = true;
- break;
-
- case NODE_LIST_ITEM:
- cr(html);
- strbuf_puts(html, "\n" : "
\n" : "\n\n");
- rstack->tight = tight;
- rstack->trim = false;
- tight = data->tight;
- visit_children = true;
- break;
-
- case NODE_ATX_HEADER:
- case NODE_SETEXT_HEADER:
- cr(html);
- strbuf_printf(html, "\n");
- }
-
- rstack = push_render_stack(rstack, b->next,
- data->list_type == CMARK_BULLET_LIST ?
- "\n
type) {
+ case NODE_PARAGRAPH:
+ if (!tight) {
+ strbuf_puts(html, "
Hello, world!
\n", "render_html"); free(html); @@ -337,7 +338,7 @@ create_tree(test_batch_runner *runner) cmark_node_unlink(emph); - html = (char *)cmark_render_html(doc); + html = cmark_render_html(doc); STR_EQ(runner, html, "Hello, !
\n", "render_html after shuffling"); free(html); @@ -439,7 +440,8 @@ test_content(test_batch_runner *runner, cmark_node_type type, cmark_node_destroy(node); } -void render_html(test_batch_runner *runner) +static void +render_html(test_batch_runner *runner) { char *html; @@ -450,18 +452,18 @@ void render_html(test_batch_runner *runner) cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1); cmark_node *paragraph = cmark_node_first_child(doc); - html = (char *)cmark_render_html(paragraph); + html = cmark_render_html(paragraph); STR_EQ(runner, html, "foo bar
\n", "render single paragraph"); free(html); cmark_node *string = cmark_node_first_child(paragraph); - html = (char *)cmark_render_html(string); + html = cmark_render_html(string); STR_EQ(runner, html, "foo ", "render single inline"); free(html); cmark_node *emph = cmark_node_next(string); - html = (char *)cmark_render_html(emph); + html = cmark_render_html(emph); STR_EQ(runner, html, "bar", "render inline with children"); free(html); diff --git a/src/cmark.c b/src/cmark.c index b20b84b..07b7c4c 100644 --- a/src/cmark.c +++ b/src/cmark.c @@ -7,10 +7,10 @@ #include "cmark.h" #include "buffer.h" -unsigned char *cmark_markdown_to_html(unsigned char *text, int len) +char *cmark_markdown_to_html(unsigned char *text, int len) { cmark_node *blocks; - unsigned char *result; + char *result; blocks = cmark_parse_document(text, len); diff --git a/src/cmark.h b/src/cmark.h index a74fe93..206b667 100644 --- a/src/cmark.h +++ b/src/cmark.h @@ -190,10 +190,10 @@ CMARK_EXPORT void cmark_debug_print(cmark_node *root); CMARK_EXPORT -unsigned char *cmark_render_html(cmark_node *root); +char *cmark_render_html(cmark_node *root); CMARK_EXPORT -unsigned char *cmark_markdown_to_html(unsigned char *text, int len); +char *cmark_markdown_to_html(unsigned char *text, int len); #ifndef CMARK_NO_SHORT_NAMES #define NODE_DOCUMENT CMARK_NODE_DOCUMENT diff --git a/src/html/html.c b/src/html/html.c index 96fce66..4fa79b1 100644 --- a/src/html/html.c +++ b/src/html/html.c @@ -348,12 +348,12 @@ finish_node(strbuf *html, cmark_node *node, bool tight) return tight; } -unsigned char *cmark_render_html(cmark_node *root) +char *cmark_render_html(cmark_node *root) { - unsigned char *result; + char *result; strbuf html = GH_BUF_INIT; node_to_html(&html, root); - result = strbuf_detach(&html); + result = (char *)strbuf_detach(&html); strbuf_free(&html); return result; } diff --git a/src/main.c b/src/main.c index 1cfddda..61d98dc 100644 --- a/src/main.c +++ b/src/main.c @@ -17,7 +17,7 @@ void print_usage() static void print_document(cmark_node *document, bool ast) { - unsigned char *result; + char *result; if (ast) { cmark_debug_print(document); } else { -- cgit v1.2.3