From 1cf1ec9a8f893a41910a300d9d8f1e6c20288287 Mon Sep 17 00:00:00 2001
From: Nick Wellnhofer Item 2 foo bar ");
+ }
+ break;
+
+ case NODE_BQUOTE:
+ cr(html);
+ strbuf_puts(html, " ");
- inlines_to_html(html, b->first_child);
- strbuf_puts(html, "\n"
+ "
\n"
"
\n"
@@ -439,6 +439,35 @@ test_content(test_batch_runner *runner, cmark_node_type type,
cmark_node_destroy(node);
}
+void render_html(test_batch_runner *runner)
+{
+ char *html;
+
+ static const unsigned char markdown[] =
+ "foo *bar*\n"
+ "\n"
+ "paragraph 2\n";
+ cmark_node *doc = cmark_parse_document(markdown, sizeof(markdown) - 1);
+
+ cmark_node *paragraph = cmark_node_first_child(doc);
+ html = (char *)cmark_render_html(paragraph);
+ STR_EQ(runner, 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, "