Пример #1
0
char *cmark_render_xml(cmark_node *root, long options)
{
	char *result;
	cmark_strbuf xml = GH_BUF_INIT;
	cmark_event_type ev_type;
	cmark_node *cur;
	struct render_state state = { &xml, 0 };

	if (options & CMARK_OPT_NORMALIZE) {
		cmark_consolidate_text_nodes(root);
	}

	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);
	cmark_strbuf_free(&xml);
	return result;
}
Пример #2
0
void cmark_consolidate_text_nodes(cmark_node *root)
{
	cmark_iter *iter = cmark_iter_new(root);
	cmark_strbuf buf = GH_BUF_INIT;
	cmark_event_type ev_type;
	cmark_node *cur, *tmp, *next;

	while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
		cur = cmark_iter_get_node(iter);
		if (ev_type == CMARK_EVENT_ENTER &&
		    cur->type == CMARK_NODE_TEXT &&
		    cur->next &&
		    cur->next->type == CMARK_NODE_TEXT) {
			cmark_strbuf_clear(&buf);
			cmark_strbuf_puts(&buf, cmark_node_get_literal(cur));
			tmp = cur->next;
			while (tmp && tmp->type == CMARK_NODE_TEXT) {
				cmark_iter_next(iter); // advance pointer
				cmark_strbuf_puts(&buf, cmark_node_get_literal(tmp));
				next = tmp->next;
				cmark_node_free(tmp);
				tmp = next;
			}
			cmark_node_set_literal(cur, (char *)cmark_strbuf_detach(&buf));
		}
	}

	cmark_iter_free(iter);
}
Пример #3
0
char *cmark_render_html_with_mem(cmark_node *root, int options, cmark_llist *extensions, cmark_mem *mem) {
  char *result;
  cmark_strbuf html = CMARK_BUF_INIT(mem);
  cmark_event_type ev_type;
  cmark_node *cur;
  cmark_html_renderer renderer = {&html, NULL, NULL, 0, 0, NULL};
  cmark_iter *iter = cmark_iter_new(root);

  for (; extensions; extensions = extensions->next)
    if (((cmark_syntax_extension *) extensions->data)->html_filter_func)
      renderer.filter_extensions = cmark_llist_append(
          mem,
          renderer.filter_extensions,
          (cmark_syntax_extension *) extensions->data);

  while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
    cur = cmark_iter_get_node(iter);
    S_render_node(&renderer, cur, ev_type, options);
  }

  if (renderer.footnote_ix) {
    cmark_strbuf_puts(&html, "</ol>\n</section>\n");
  }

  result = (char *)cmark_strbuf_detach(&html);

  cmark_llist_free(mem, renderer.filter_extensions);

  cmark_iter_free(iter);
  return result;
}
Пример #4
0
static unsigned char *cmark_clean_autolink(cmark_chunk *url, int is_email)
{
	cmark_strbuf buf = GH_BUF_INIT;

	cmark_chunk_trim(url);

	if (url->len == 0)
		return NULL;

	if (is_email)
		cmark_strbuf_puts(&buf, "mailto:");

	houdini_unescape_html_f(&buf, url->data, url->len);
	return cmark_strbuf_detach(&buf);
}
Пример #5
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, 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;
}
Пример #6
0
// Clean a URL: remove surrounding whitespace and surrounding <>,
// and remove \ that escape punctuation.
unsigned char *cmark_clean_url(cmark_chunk *url)
{
	cmark_strbuf buf = GH_BUF_INIT;

	cmark_chunk_trim(url);

	if (url->len == 0)
		return NULL;

	if (url->data[0] == '<' && url->data[url->len - 1] == '>') {
		houdini_unescape_html_f(&buf, url->data + 1, url->len - 2);
	} else {
		houdini_unescape_html_f(&buf, url->data, url->len);
	}

	cmark_strbuf_unescape(&buf);
	return cmark_strbuf_detach(&buf);
}
Пример #7
0
char *cmark_render_html(cmark_node *root, int options)
{
	char *result;
	cmark_strbuf html = GH_BUF_INIT;
	cmark_event_type ev_type;
	cmark_node *cur;
	struct render_state state = { &html, NULL };
	cmark_iter *iter = cmark_iter_new(root);

	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(&html);

	cmark_iter_free(iter);
	return result;
}
Пример #8
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;
}
Пример #9
0
unsigned char *cmark_clean_title(cmark_chunk *title)
{
	cmark_strbuf buf = GH_BUF_INIT;
	unsigned char first, last;

	if (title->len == 0)
		return NULL;

	first = title->data[0];
	last = title->data[title->len - 1];

	// remove surrounding quotes if any:
	if ((first == '\'' && last == '\'') ||
	    (first == '(' && last == ')') ||
	    (first == '"' && last == '"')) {
		houdini_unescape_html_f(&buf, title->data + 1, title->len - 2);
	} else {
		houdini_unescape_html_f(&buf, title->data, title->len);
	}

	cmark_strbuf_unescape(&buf);
	return cmark_strbuf_detach(&buf);
}
Пример #10
0
// normalize reference:  collapse internal whitespace to single space,
// remove leading/trailing whitespace, case fold
// Return NULL if the reference name is actually empty (i.e. composed
// solely from whitespace)
static unsigned char *normalize_reference(cmark_mem *mem, cmark_chunk *ref) {
  cmark_strbuf normalized = CMARK_BUF_INIT(mem);
  unsigned char *result;

  if (ref == NULL)
    return NULL;

  if (ref->len == 0)
    return NULL;

  cmark_utf8proc_case_fold(&normalized, ref->data, ref->len);
  cmark_strbuf_trim(&normalized);
  cmark_strbuf_normalize_whitespace(&normalized);

  result = cmark_strbuf_detach(&normalized);
  assert(result);

  if (result[0] == '\0') {
    free(result);
    return NULL;
  }

  return result;
}