summaryrefslogtreecommitdiff
path: root/src/html.c
diff options
context:
space:
mode:
authorJohn MacFarlane <jgm@berkeley.edu>2014-12-29 12:20:19 -0800
committerJohn MacFarlane <jgm@berkeley.edu>2014-12-29 12:50:58 -0800
commit0566fa09cf2369cef3ea6b459f3d4fcf3a27d0fc (patch)
treeadae2b1e8da52a6edfdb459cba975b257eae2f9a /src/html.c
parent96c7df6a8480b78ddc2540dd85877487af358ceb (diff)
Added options parameter to renderers.
To keep the API simple and avoid API changes when new options are added, this is just a long integer. Set it by disjoining options that are defined as powers of 2: e.g. `CMARK_HTML_SOURCEPOS | CMARK_HTML_HARDREAKS`. Test options using `&`: `if (options & CMARK_HTML_SOURCEPOS)`. Added `--hardbreaks` and `--sourcepos` command-line options.
Diffstat (limited to 'src/html.c')
-rw-r--r--src/html.c71
1 files changed, 54 insertions, 17 deletions
diff --git a/src/html.c b/src/html.c
index 80e8d6d..67c93e9 100644
--- a/src/html.c
+++ b/src/html.c
@@ -38,15 +38,27 @@ struct render_state {
cmark_node *plain;
};
+static void
+S_render_sourcepos(cmark_node *node, cmark_strbuf *html, long options) {
+ if (CMARK_OPT_SOURCEPOS & options) {
+ cmark_strbuf_printf(html, " data-sourcepos=\"%d:%d-%d:%d\"",
+ cmark_node_get_start_line(node),
+ cmark_node_get_start_column(node),
+ cmark_node_get_end_line(node),
+ cmark_node_get_end_column(node));
+ }
+}
+
static int
-S_render_node(cmark_node *node, cmark_event_type ev_type, void *vstate)
+S_render_node(cmark_node *node, cmark_event_type ev_type, void *vstate,
+ long options)
{
struct render_state *state = vstate;
cmark_node *parent;
cmark_node *grandparent;
cmark_strbuf *html = state->html;
- char start_header[] = "<h0>";
- char end_header[] = "</h0>";
+ char start_header[] = "<h0";
+ char end_header[] = "</h0";
bool tight;
bool entering = (ev_type == CMARK_EVENT_ENTER);
@@ -82,7 +94,9 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, void *vstate)
case CMARK_NODE_BLOCK_QUOTE:
if (entering) {
cr(html);
- cmark_strbuf_puts(html, "<blockquote>\n");
+ cmark_strbuf_puts(html, "<blockquote");
+ S_render_sourcepos(node, html, options);
+ cmark_strbuf_puts(html, ">\n");
} else {
cr(html);
cmark_strbuf_puts(html, "</blockquote>\n");
@@ -96,14 +110,21 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, void *vstate)
if (entering) {
cr(html);
if (list_type == CMARK_BULLET_LIST) {
- cmark_strbuf_puts(html, "<ul>\n");
+ cmark_strbuf_puts(html, "<ul");
+ S_render_sourcepos(node, html, options);
+ cmark_strbuf_puts(html, ">\n");
}
else if (start == 1) {
- cmark_strbuf_puts(html, "<ol>\n");
+ cmark_strbuf_puts(html, "<ol");
+ S_render_sourcepos(node, html, options);
+ cmark_strbuf_puts(html, ">\n");
}
else {
- cmark_strbuf_printf(html, "<ol start=\"%d\">\n",
- start);
+ cmark_strbuf_printf(html,
+ "<ol start=\"%d\"",
+ start);
+ S_render_sourcepos(node, html, options);
+ cmark_strbuf_puts(html, ">\n");
}
} else {
cmark_strbuf_puts(html,
@@ -116,7 +137,9 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, void *vstate)
case CMARK_NODE_ITEM:
if (entering) {
cr(html);
- cmark_strbuf_puts(html, "<li>");
+ cmark_strbuf_puts(html, "<li");
+ S_render_sourcepos(node, html, options);
+ cmark_strbuf_putc(html, '>');
} else {
cmark_strbuf_puts(html, "</li>\n");
}
@@ -127,10 +150,12 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, void *vstate)
cr(html);
start_header[2] = '0' + node->as.header.level;
cmark_strbuf_puts(html, start_header);
+ S_render_sourcepos(node, html, options);
+ cmark_strbuf_putc(html, '>');
} else {
end_header[3] = '0' + node->as.header.level;
cmark_strbuf_puts(html, end_header);
- cmark_strbuf_putc(html, '\n');
+ cmark_strbuf_puts(html, ">\n");
}
break;
@@ -138,7 +163,9 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, void *vstate)
cr(html);
if (!node->as.code.fenced || node->as.code.info.len == 0) {
- cmark_strbuf_puts(html, "<pre><code>");
+ cmark_strbuf_puts(html, "<pre");
+ S_render_sourcepos(node, html, options);
+ cmark_strbuf_puts(html, "><code>");
}
else {
int first_tag = 0;
@@ -147,7 +174,9 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, void *vstate)
first_tag += 1;
}
- cmark_strbuf_puts(html, "<pre><code class=\"language-");
+ cmark_strbuf_puts(html, "<pre");
+ S_render_sourcepos(node, html, options);
+ cmark_strbuf_puts(html, "><code class=\"language-");
escape_html(html, node->as.code.info.data, first_tag);
cmark_strbuf_puts(html, "\">");
}
@@ -164,7 +193,9 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, void *vstate)
case CMARK_NODE_HRULE:
cr(html);
- cmark_strbuf_puts(html, "<hr />\n");
+ cmark_strbuf_puts(html, "<hr");
+ S_render_sourcepos(node, html, options);
+ cmark_strbuf_puts(html, " />\n");
break;
case CMARK_NODE_PARAGRAPH:
@@ -179,7 +210,9 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, void *vstate)
if (!tight) {
if (entering) {
cr(html);
- cmark_strbuf_puts(html, "<p>");
+ cmark_strbuf_puts(html, "<p");
+ S_render_sourcepos(node, html, options);
+ cmark_strbuf_putc(html, '>');
} else {
cmark_strbuf_puts(html, "</p>\n");
}
@@ -196,7 +229,11 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, void *vstate)
break;
case CMARK_NODE_SOFTBREAK:
- cmark_strbuf_putc(html, '\n');
+ if (options & CMARK_OPT_HARDBREAKS) {
+ cmark_strbuf_puts(html, "<br />\n");
+ } else {
+ cmark_strbuf_putc(html, '\n');
+ }
break;
case CMARK_NODE_CODE:
@@ -269,7 +306,7 @@ S_render_node(cmark_node *node, cmark_event_type ev_type, void *vstate)
return 1;
}
-char *cmark_render_html(cmark_node *root)
+char *cmark_render_html(cmark_node *root, long options)
{
char *result;
cmark_strbuf html = GH_BUF_INIT;
@@ -280,7 +317,7 @@ char *cmark_render_html(cmark_node *root)
while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
cur = cmark_iter_get_node(iter);
- S_render_node(cur, ev_type, &state);
+ S_render_node(cur, ev_type, &state, options);
}
result = (char *)cmark_strbuf_detach(&html);