예제 #1
0
파일: node.c 프로젝트: tin-pot/cmark
static void S_print_error(FILE *out, cmark_node *node, const char *elem) {
  if (out == NULL) {
    return;
  }
  fprintf(out, "Invalid '%s' in node type %s at %d:%d\n", elem,
          cmark_node_get_type_string(node), node->start_line,
          node->start_column);
}
예제 #2
0
static int
S_render_node(cmark_node *node, cmark_event_type ev_type,
              struct render_state *state, long options)
{
	cmark_strbuf *xml = state->xml;
	bool literal = false;
	cmark_delim_type delim;
	bool entering = (ev_type == CMARK_EVENT_ENTER);

	if (entering) {
		indent(state);
		cmark_strbuf_printf(xml, "<%s",
		                    cmark_node_get_type_string(node));

		if (options & CMARK_OPT_SOURCEPOS && node->start_line != 0) {
			cmark_strbuf_printf(xml, " sourcepos=\"%d:%d-%d:%d\"",
			                    node->start_line,
			                    node->start_column,
			                    node->end_line,
			                    node->end_column);
		}

		literal = false;

		switch (node->type) {
		case CMARK_NODE_TEXT:
		case CMARK_NODE_CODE:
		case CMARK_NODE_HTML:
		case CMARK_NODE_INLINE_HTML:
			cmark_strbuf_puts(xml, ">");
			escape_xml(xml, node->as.literal.data,
			           node->as.literal.len);
			cmark_strbuf_puts(xml, "</");
			cmark_strbuf_puts(xml,
			                  cmark_node_get_type_string(node));
			literal = true;
			break;
		case CMARK_NODE_LIST:
			switch (cmark_node_get_list_type(node)) {
			case CMARK_ORDERED_LIST:
				cmark_strbuf_puts(xml, " type=\"ordered\"");
				cmark_strbuf_printf(xml, " start=\"%d\"",
				                    cmark_node_get_list_start(node));
				delim = cmark_node_get_list_delim(node);
				if (delim == CMARK_PAREN_DELIM) {
					cmark_strbuf_puts(xml,
					                  " delim=\"paren\"");
				} else if (delim == CMARK_PERIOD_DELIM) {
					cmark_strbuf_puts(xml,
					                  " delim=\"period\"");
				}
				break;
			case CMARK_BULLET_LIST:
				cmark_strbuf_puts(xml, " type=\"bullet\"");
				break;
			default:
				break;
			}
			cmark_strbuf_printf(xml, " tight=\"%s\"",
			                    (cmark_node_get_list_tight(node) ?
			                     "true" : "false"));
			break;
		case CMARK_NODE_HEADER:
			cmark_strbuf_printf(xml, " level=\"%d\"",
			                    node->as.header.level);
			break;
		case CMARK_NODE_CODE_BLOCK:
			if (node->as.code.info.len > 0) {
				cmark_strbuf_puts(xml, " info=\"");
				escape_xml(xml, node->as.code.info.data,
				           node->as.code.info.len);
				cmark_strbuf_putc(xml, '"');
			}
			cmark_strbuf_puts(xml, ">");
			escape_xml(xml, node->as.code.literal.data,
			           node->as.code.literal.len);
			cmark_strbuf_puts(xml, "</");
			cmark_strbuf_puts(xml,
			                  cmark_node_get_type_string(node));
			literal = true;
			break;
		case CMARK_NODE_LINK:
		case CMARK_NODE_IMAGE:
			cmark_strbuf_puts(xml, " destination=\"");
			escape_xml(xml, node->as.link.url, -1);
			cmark_strbuf_putc(xml, '"');
			cmark_strbuf_puts(xml, " title=\"");
			escape_xml(xml, node->as.link.title, -1);
			cmark_strbuf_putc(xml, '"');
			break;
		default:
			break;
		}
		if (node->first_child) {
			state->indent += 2;
		} else if (!literal) {
			cmark_strbuf_puts(xml, " /");
		}
		cmark_strbuf_puts(xml, ">\n");


	} else if (node->first_child) {
		state->indent -= 2;
		indent(state);
		cmark_strbuf_printf(xml, "</%s>\n",
		                    cmark_node_get_type_string(node));
	}

	return 1;
}