Пример #1
0
static void print_str(strbuf* buffer, const unsigned char *s, int len)
{
	int i;

	if (len < 0)
		len = strlen((char *)s);

	strbuf_putc(buffer, '"');
	for (i = 0; i < len; ++i) {
		unsigned char c = s[i];

		switch (c) {
		case '\n':
			strbuf_printf(buffer, "\\n");
			break;
		case '"':
			strbuf_printf(buffer, "\\\"");
			break;
		case '\\':
			strbuf_printf(buffer, "\\\\");
			break;
		default:
			strbuf_putc(buffer, (int)c);
		}
	}
	strbuf_putc(buffer, '"');
}
Пример #2
0
// Prettyprint an inline list, for debugging.
static void render_nodes(strbuf* buffer, cmark_node* node, int indent)
{
	int i;
	cmark_list *data;

	while(node != NULL) {
		for (i=0; i < indent; i++) {
			strbuf_putc(buffer, ' ');
		}
		switch(node->type) {
		case NODE_DOCUMENT:
			break;
		case NODE_BLOCK_QUOTE:
			strbuf_printf(buffer, "block_quote\n");
			break;
		case NODE_LIST_ITEM:
			strbuf_printf(buffer, "list_item\n");
			break;
		case NODE_LIST:
			data = &(node->as.list);
			if (data->list_type == CMARK_ORDERED_LIST) {
				strbuf_printf(buffer, "list (type=ordered tight=%s start=%d delim=%s)\n",
				       (data->tight ? "true" : "false"),
				       data->start,
				       (data->delimiter == CMARK_PAREN_DELIM ? "parens" : "period"));
			} else {
				strbuf_printf(buffer, "list (type=bullet tight=%s bullet_char=%c)\n",
				       (data->tight ? "true" : "false"),
				       data->bullet_char);
			}
			break;
		case NODE_HEADER:
			strbuf_printf(buffer, "header (level=%d)\n", node->as.header.level);
			break;
		case NODE_PARAGRAPH:
			strbuf_printf(buffer, "paragraph\n");
			break;
		case NODE_HRULE:
			strbuf_printf(buffer, "hrule\n");
			break;
		case NODE_CODE_BLOCK:
			strbuf_printf(buffer, "code_block info=");
			print_str(buffer, node->as.code.info.ptr, -1);
			strbuf_putc(buffer, ' ');
			print_str(buffer, node->string_content.ptr, -1);
			strbuf_putc(buffer, '\n');
			break;
		case NODE_HTML:
			strbuf_printf(buffer, "html ");
			print_str(buffer, node->string_content.ptr, -1);
			strbuf_putc(buffer, '\n');
			break;
		case NODE_TEXT:
			strbuf_printf(buffer, "text ");
			print_str(buffer, node->as.literal.data, node->as.literal.len);
			strbuf_putc(buffer, '\n');
			break;
		case NODE_LINEBREAK:
			strbuf_printf(buffer, "linebreak\n");
			break;
		case NODE_SOFTBREAK:
			strbuf_printf(buffer, "softbreak\n");
			break;
		case NODE_INLINE_CODE:
			strbuf_printf(buffer, "code ");
			print_str(buffer, node->as.literal.data, node->as.literal.len);
			strbuf_putc(buffer, '\n');
			break;
		case NODE_INLINE_HTML:
			strbuf_printf(buffer, "inline_html ");
			print_str(buffer, node->as.literal.data, node->as.literal.len);
			strbuf_putc(buffer, '\n');
			break;
		case NODE_LINK:
		case NODE_IMAGE:
			strbuf_printf(buffer, "%s url=", node->type == NODE_LINK ? "link" : "image");

			if (node->as.link.url)
				print_str(buffer, node->as.link.url, -1);

			if (node->as.link.title) {
				strbuf_printf(buffer, " title=");
				print_str(buffer, node->as.link.title, -1);
			}
			strbuf_putc(buffer, '\n');
			break;
		case NODE_STRONG:
			strbuf_printf(buffer, "strong\n");
			break;
		case NODE_EMPH:
			strbuf_printf(buffer, "emph\n");
			break;
		default:
			break;
		}
		if (node->first_child) { // render children if any
			indent += INDENT;
			node = node->first_child;
		} else if (node->next) { // otherwise render next sibling
			node = node->next;
		} else {
			node = node->parent;  // back up to parent
			while (node) {
				indent -= INDENT;
				if (node->next) {
					node = node->next;
					break;
				} else {
					node = node->parent;
				}
				if (!node) {
					break;
				}
			}
		}
	}
}
Пример #3
0
// Convert a node_block list to HTML.  Returns 0 on success, and sets result.
static void blocks_to_html(strbuf *html, node_block *b)
{
	struct ListData *data;
	render_stack* rstack = NULL;
	bool visit_children = false;
	bool tight = false;

	while(b != NULL) {
		visit_children = false;
		switch(b->tag) {
		case BLOCK_DOCUMENT:
			rstack = push_block(rstack, b->next, "", false, false);
			visit_children = true;
			break;

		case BLOCK_PARAGRAPH:
			if (tight) {
				inlines_to_html(html, b->inline_content);
			} else {
				cr(html);
				strbuf_puts(html, "<p>");
				inlines_to_html(html, b->inline_content);
				strbuf_puts(html, "</p>\n");
			}
			break;

		case BLOCK_BQUOTE:
			cr(html);
			strbuf_puts(html, "<blockquote>\n");
			rstack = push_block(rstack, b->next, "</blockquote>\n", tight, false);
			tight = false;
			visit_children = true;
			break;

		case BLOCK_LIST_ITEM:
			cr(html);
			strbuf_puts(html, "<li>");
			rstack = push_block(rstack, b->next, "</li>\n", tight, true);
			visit_children = true;
			break;

		case BLOCK_LIST:
			// make sure a list starts at the beginning of the line:
			cr(html);
			data = &(b->as.list);

			if (data->start > 1) {
				strbuf_printf(html, "<%s start=\"%d\">\n",
					      data->list_type == bullet ? "ul" : "ol",
					      data->start);
			} else {
				strbuf_puts(html, data->list_type == bullet ? "<ul>\n" : "<ol>\n");
			}

			rstack = push_block(rstack, b->next,
					    data->list_type == bullet ?
					    "\n</ul>\n" : "\n</ol>\n", tight, false);
			tight = data->tight;
			visit_children = true;
			break;

		case BLOCK_ATX_HEADER:
		case BLOCK_SETEXT_HEADER:
			cr(html);
			strbuf_printf(html, "<h%d>", b->as.header.level);
			inlines_to_html(html, b->inline_content);
			strbuf_printf(html, "</h%d>\n", b->as.header.level);
			break;

		case BLOCK_INDENTED_CODE:
		case BLOCK_FENCED_CODE:
			cr(html);

			strbuf_puts(html, "<pre><code");

			if (b->tag == BLOCK_FENCED_CODE) {
				strbuf *info = &b->as.code.info;

				if (strbuf_len(info) > 0) {
					int first_tag = strbuf_strchr(info, ' ', 0);
					if (first_tag < 0)
						first_tag = strbuf_len(info);

					strbuf_puts(html, " class=\"language-");
					escape_html(html, info->ptr, first_tag);
					strbuf_putc(html, '"');
				}
			}

			strbuf_putc(html, '>');
			escape_html(html, b->string_content.ptr, b->string_content.size);
			strbuf_puts(html, "</code></pre>\n");
			break;

		case BLOCK_HTML:
			strbuf_put(html, b->string_content.ptr, b->string_content.size);
			break;

		case BLOCK_HRULE:
			strbuf_puts(html, "<hr />\n");
			break;

		case BLOCK_REFERENCE_DEF:
			break;

		default:
			assert(false);
		}
		if (visit_children) {
			b = b->children;
		} else {
			b = b->next;
		}
		while (b == NULL && rstack != NULL) {
			strbuf_puts(html, rstack->literal);
			if (rstack->trim) {
				strbuf_rtrim(html);
			}
			tight = rstack->tight;
			b = rstack->next_sibling.block;
			rstack = pop_render_stack(rstack);
		}
	}

	free_render_stack(rstack);
}