Пример #1
0
Файл: main.c Проект: safx/cmark
static void
iterator(test_batch_runner *runner) {
	cmark_node *doc = cmark_parse_document("> a *b*\n\nc", 10, CMARK_OPT_DEFAULT);
	int parnodes = 0;
	cmark_event_type ev_type;
	cmark_iter *iter = cmark_iter_new(doc);
	cmark_node *cur;

	while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
		cur = cmark_iter_get_node(iter);
		if (cur->type == CMARK_NODE_PARAGRAPH &&
		    ev_type == CMARK_EVENT_ENTER) {
			parnodes += 1;
		}
	}
	INT_EQ(runner, parnodes, 2, "iterate correctly counts paragraphs");

	cmark_iter_free(iter);
	cmark_node_free(doc);
}
Пример #2
0
char *cmark_render(cmark_node *root, int options, int width,
                   void (*outc)(cmark_renderer *, cmark_escaping, int32_t,
                                unsigned char),
                   int (*render_node)(cmark_renderer *renderer,
                                      cmark_node *node,
                                      cmark_event_type ev_type, int options)) {
    cmark_strbuf pref = GH_BUF_INIT;
    cmark_strbuf buf = GH_BUF_INIT;
    cmark_node *cur;
    cmark_event_type ev_type;
    char *result;
    cmark_iter *iter = cmark_iter_new(root);

    cmark_renderer renderer = {&buf,  &pref, 0,    width, 0,           0,    true,
                               true, false, false,
                               outc, S_cr,  S_blankline, S_out
                              };

    while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
        cur = cmark_iter_get_node(iter);
        if (!render_node(&renderer, cur, ev_type, options)) {
            // a false value causes us to skip processing
            // the node's contents.  this is used for
            // autolinks.
            cmark_iter_reset(iter, cur, CMARK_EVENT_EXIT);
        }
    }

    // ensure final newline
    if (renderer.buffer->ptr[renderer.buffer->size - 1] != '\n') {
        cmark_strbuf_putc(renderer.buffer, '\n');
    }

    result = (char *)cmark_strbuf_detach(renderer.buffer);

    cmark_iter_free(iter);
    cmark_strbuf_free(renderer.prefix);
    cmark_strbuf_free(renderer.buffer);

    return result;
}
Пример #3
0
char *cmark_render_man(cmark_node *root, long options)
{
	char *result;
	cmark_strbuf man = GH_BUF_INIT;
	struct render_state state = { &man, NULL };
	cmark_node *cur;
	cmark_event_type ev_type;
	cmark_iter *iter = cmark_iter_new(root);

	if (options == 0) options = 0; // avoid warning about unused parameters

	while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
		cur = cmark_iter_get_node(iter);
		S_render_node(cur, ev_type, &state);
	}
	result = (char *)cmark_strbuf_detach(&man);

	cmark_iter_free(iter);
	cmark_strbuf_free(&man);
	return result;
}
Пример #4
0
int md_process(cmark_node *const node) {
	assert(node);
	cmark_iter *iter = cmark_iter_new(node);
	assert(iter);

	// Due to the way cmark_iter_reset works, we're missing
	// the first event each time. But that's fine.
	cmark_iter_reset(iter, node, CMARK_EVENT_ENTER);
	md_escape(iter);
	cmark_iter_reset(iter, node, CMARK_EVENT_ENTER);
	md_escape_inline(iter);
	cmark_iter_reset(iter, node, CMARK_EVENT_ENTER);
	md_autolink(iter);
	cmark_iter_reset(iter, node, CMARK_EVENT_ENTER);
	md_block_external_images(iter);
	cmark_iter_reset(iter, node, CMARK_EVENT_ENTER);
	md_convert_hashes(iter);

	cmark_iter_free(iter); iter = NULL;
	return 0;
}
Пример #5
0
char *cmark_render_xml(cmark_node *root, int options) {
  char *result;
  cmark_strbuf xml = GH_BUF_INIT;
  cmark_event_type ev_type;
  cmark_node *cur;
  struct render_state state = {&xml, 0};

  cmark_iter *iter = cmark_iter_new(root);

  cmark_strbuf_puts(state.xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
  cmark_strbuf_puts(state.xml,
                    "<!DOCTYPE CommonMark SYSTEM \"CommonMark.dtd\">\n");
  while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
    cur = cmark_iter_get_node(iter);
    S_render_node(cur, ev_type, &state, options);
  }
  result = (char *)cmark_strbuf_detach(&xml);

  cmark_iter_free(iter);
  return result;
}
Пример #6
0
Файл: main.c Проект: txdv/cmark
static void
iterator_delete(test_batch_runner *runner) {
	static const char md[] =
		"a *b* c\n"
		"\n"
		"* item1\n"
		"* item2\n"
		"\n"
		"a `b` c\n"
		"\n"
		"* item1\n"
		"* item2\n";
	cmark_node *doc  = cmark_parse_document(md, sizeof(md) - 1,
						CMARK_OPT_DEFAULT);
	cmark_iter *iter = cmark_iter_new(doc);
	cmark_event_type ev_type;

	while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
		cmark_node *node = cmark_iter_get_node(iter);
		// Delete list, emph, and code nodes.
		if ((ev_type == CMARK_EVENT_EXIT &&
		     node->type == CMARK_NODE_LIST) ||
		    (ev_type == CMARK_EVENT_EXIT &&
		     node->type == CMARK_NODE_EMPH) ||
		    (ev_type == CMARK_EVENT_ENTER &&
		     node->type == CMARK_NODE_CODE)) {
			cmark_node_free(node);
		}
	}

	char *html = cmark_render_html(doc, CMARK_OPT_DEFAULT);
	static const char expected[] =
		"<p>a  c</p>\n"
		"<p>a  c</p>\n";
	STR_EQ(runner, html, expected, "iterate and delete nodes");

	free(html);
	cmark_iter_free(iter);
	cmark_node_free(doc);
}
Пример #7
0
// Convert a single node.
static char*
S_node_to_pod(cmark_node *node, CFCClass *klass, int header_level) {
    char *result = CFCUtil_strdup("");
    if (node == NULL) {
        return result;
    }

    int found_matching_code_block = false;
    cmark_iter *iter = cmark_iter_new(node);
    cmark_event_type ev_type;

    while (CMARK_EVENT_DONE != (ev_type = cmark_iter_next(iter))) {
        cmark_node *node = cmark_iter_get_node(iter);
        cmark_node_type type = cmark_node_get_type(node);

        switch (type) {
            case CMARK_NODE_DOCUMENT:
                break;

            case CMARK_NODE_PARAGRAPH:
                if (ev_type == CMARK_EVENT_EXIT) {
                    result = CFCUtil_cat(result, "\n\n", NULL);
                }
                break;

            case CMARK_NODE_BLOCK_QUOTE:
            case CMARK_NODE_LIST:
                if (ev_type == CMARK_EVENT_ENTER) {
                    result = CFCUtil_cat(result, "=over\n\n", NULL);
                }
                else {
                    result = CFCUtil_cat(result, "=back\n\n", NULL);
                }
                break;

            case CMARK_NODE_ITEM:
                // TODO: Ordered lists.
                if (ev_type == CMARK_EVENT_ENTER) {
                    result = CFCUtil_cat(result, "=item *\n\n", NULL);
                }
                break;

            case CMARK_NODE_HEADER:
                if (ev_type == CMARK_EVENT_ENTER) {
                    int extra_level = cmark_node_get_header_level(node) - 1;
                    char *header = CFCUtil_sprintf("=head%d ",
                                                   header_level + extra_level);
                    result = CFCUtil_cat(result, header, NULL);
                    FREEMEM(header);
                }
                else {
                    result = CFCUtil_cat(result, "\n\n", NULL);
                }
                break;

            case CMARK_NODE_CODE_BLOCK: {
                int is_host = CFCMarkdown_code_block_is_host(node, "perl");

                if (is_host) {
                    found_matching_code_block = true;

                    const char *content = cmark_node_get_literal(node);
                    char *copy = CFCUtil_strdup(content);
                    // Chomp trailing newline.
                    size_t len = strlen(copy);
                    if (len > 0 && copy[len-1] == '\n') {
                        copy[len-1] = '\0';
                    }
                    char *indented
                        = CFCUtil_global_replace(copy, "\n", "\n    ");
                    result
                        = CFCUtil_cat(result, "    ", indented, "\n\n", NULL);
                    FREEMEM(indented);
                    FREEMEM(copy);
                }

                if (CFCMarkdown_code_block_is_last(node)) {
                    if (!found_matching_code_block) {
                        result = CFCUtil_cat(result,
                            "    Code example for Perl is missing\n\n");
                    }
                    else {
                        // Reset.
                        found_matching_code_block = false;
                    }
                }

                break;
            }

            case CMARK_NODE_HTML: {
                const char *html = cmark_node_get_literal(node);
                result = CFCUtil_cat(result, "=begin html\n\n", html,
                                     "\n=end\n\n", NULL);
                break;
            }

            case CMARK_NODE_HRULE:
                break;

            case CMARK_NODE_TEXT: {
                const char *content = cmark_node_get_literal(node);
                char *escaped = S_pod_escape(content);
                result = CFCUtil_cat(result, escaped, NULL);
                FREEMEM(escaped);
                break;
            }

            case CMARK_NODE_LINEBREAK:
                // POD doesn't support line breaks. Start a new paragraph.
                result = CFCUtil_cat(result, "\n\n", NULL);
                break;

            case CMARK_NODE_SOFTBREAK:
                result = CFCUtil_cat(result, "\n", NULL);
                break;

            case CMARK_NODE_CODE: {
                const char *content = cmark_node_get_literal(node);
                char *escaped = S_pod_escape(content);
                result = CFCUtil_cat(result, "C<", escaped, ">", NULL);
                FREEMEM(escaped);
                break;
            }

            case CMARK_NODE_INLINE_HTML: {
                const char *html = cmark_node_get_literal(node);
                CFCUtil_warn("Inline HTML not supported in POD: %s", html);
                break;
            }

            case CMARK_NODE_LINK:
                if (ev_type == CMARK_EVENT_ENTER) {
                    char *pod = S_convert_link(node, klass, header_level);
                    result = CFCUtil_cat(result, pod, NULL);
                    FREEMEM(pod);
                    cmark_iter_reset(iter, node, CMARK_EVENT_EXIT);
                }
                break;

            case CMARK_NODE_IMAGE:
                CFCUtil_warn("Images not supported in POD");
                break;

            case CMARK_NODE_STRONG:
                if (ev_type == CMARK_EVENT_ENTER) {
                    result = CFCUtil_cat(result, "B<", NULL);
                }
                else {
                    result = CFCUtil_cat(result, ">", NULL);
                }
                break;

            case CMARK_NODE_EMPH:
                if (ev_type == CMARK_EVENT_ENTER) {
                    result = CFCUtil_cat(result, "I<", NULL);
                }
                else {
                    result = CFCUtil_cat(result, ">", NULL);
                }
                break;

            default:
                CFCUtil_die("Invalid cmark node type: %d", (int)type);
                break;
        }
    }

    cmark_iter_free(iter);
    return result;
}