Merge pull request #124 from jmendeth/renderer-api

Renderer API
This commit is contained in:
Devin Torres 2014-10-02 22:16:52 -05:00
commit 758951ba6d
4 changed files with 239 additions and 198 deletions

View file

@ -114,9 +114,9 @@ static char_trigger markdown_char_ptrs[] = {
&char_math
};
/* render • structure containing state for a parser instance */
struct hoedown_document {
hoedown_renderer md;
hoedown_renderer_data data;
struct link_ref *refs[REF_TABLE_SIZE];
struct footnote_list footnotes_found;
@ -475,7 +475,7 @@ parse_inline(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t si
if (doc->md.normal_text) {
work.data = data + i;
work.size = end - i;
doc->md.normal_text(ob, &work, doc->md.opaque);
doc->md.normal_text(ob, &work, &doc->data);
}
else
hoedown_buffer_put(ob, data + i, end - i);
@ -627,9 +627,9 @@ parse_emph1(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t siz
parse_inline(work, doc, data, i);
if (doc->ext_flags & HOEDOWN_EXT_UNDERLINE && c == '_')
r = doc->md.underline(ob, work, doc->md.opaque);
r = doc->md.underline(ob, work, &doc->data);
else
r = doc->md.emphasis(ob, work, doc->md.opaque);
r = doc->md.emphasis(ob, work, &doc->data);
popbuf(doc, BUFFER_SPAN);
return r ? i + 1 : 0;
@ -657,11 +657,11 @@ parse_emph2(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t siz
parse_inline(work, doc, data, i);
if (c == '~')
r = doc->md.strikethrough(ob, work, doc->md.opaque);
r = doc->md.strikethrough(ob, work, &doc->data);
else if (c == '=')
r = doc->md.highlight(ob, work, doc->md.opaque);
r = doc->md.highlight(ob, work, &doc->data);
else
r = doc->md.double_emphasis(ob, work, doc->md.opaque);
r = doc->md.double_emphasis(ob, work, &doc->data);
popbuf(doc, BUFFER_SPAN);
return r ? i + 2 : 0;
@ -693,7 +693,7 @@ parse_emph3(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t siz
hoedown_buffer *work = newbuf(doc, BUFFER_SPAN);
parse_inline(work, doc, data, i);
r = doc->md.triple_emphasis(ob, work, doc->md.opaque);
r = doc->md.triple_emphasis(ob, work, &doc->data);
popbuf(doc, BUFFER_SPAN);
return r ? i + 3 : 0;
@ -741,7 +741,7 @@ parse_math(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offs
displaymode = is_empty_all(data - offset, offset) && is_empty_all(data + i, size - i);
/* call callback */
if (doc->md.math(ob, &text, displaymode, doc->md.opaque))
if (doc->md.math(ob, &text, displaymode, &doc->data))
return i;
return 0;
}
@ -796,7 +796,7 @@ char_linebreak(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
while (ob->size && ob->data[ob->size - 1] == ' ')
ob->size--;
return doc->md.linebreak(ob, doc->md.opaque) ? 1 : 0;
return doc->md.linebreak(ob, &doc->data) ? 1 : 0;
}
@ -832,10 +832,10 @@ char_codespan(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t o
/* real code span */
if (f_begin < f_end) {
hoedown_buffer work = { data + f_begin, f_end - f_begin, 0, 0, NULL, NULL, NULL };
if (!doc->md.codespan(ob, &work, doc->md.opaque))
if (!doc->md.codespan(ob, &work, &doc->data))
end = 0;
} else {
if (!doc->md.codespan(ob, 0, doc->md.opaque))
if (!doc->md.codespan(ob, 0, &doc->data))
end = 0;
}
@ -877,11 +877,11 @@ char_quote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offs
hoedown_buffer *work = newbuf(doc, BUFFER_SPAN);
parse_inline(work, doc, data + f_begin, f_end - f_begin);
if (!doc->md.quote(ob, work, doc->md.opaque))
if (!doc->md.quote(ob, work, &doc->data))
end = 0;
popbuf(doc, BUFFER_SPAN);
} else {
if (!doc->md.quote(ob, 0, doc->md.opaque))
if (!doc->md.quote(ob, 0, &doc->data))
end = 0;
}
@ -911,7 +911,7 @@ char_escape(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t off
if (doc->md.normal_text) {
work.data = data + 1;
work.size = 1;
doc->md.normal_text(ob, &work, doc->md.opaque);
doc->md.normal_text(ob, &work, &doc->data);
}
else hoedown_buffer_putc(ob, data[1]);
} else if (size == 1) {
@ -943,7 +943,7 @@ char_entity(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t off
if (doc->md.entity) {
work.data = data;
work.size = end;
doc->md.entity(ob, &work, doc->md.opaque);
doc->md.entity(ob, &work, &doc->data);
}
else hoedown_buffer_put(ob, data, end);
@ -965,11 +965,11 @@ char_langle_tag(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
work.data = data + 1;
work.size = end - 2;
unscape_text(u_link, &work);
ret = doc->md.autolink(ob, u_link, altype, doc->md.opaque);
ret = doc->md.autolink(ob, u_link, altype, &doc->data);
popbuf(doc, BUFFER_SPAN);
}
else if (doc->md.raw_html_tag)
ret = doc->md.raw_html_tag(ob, &work, doc->md.opaque);
else if (doc->md.raw_html)
ret = doc->md.raw_html(ob, &work, &doc->data);
}
if (!ret) return 0;
@ -995,11 +995,11 @@ char_autolink_www(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size
ob->size -= rewind;
if (doc->md.normal_text) {
link_text = newbuf(doc, BUFFER_SPAN);
doc->md.normal_text(link_text, link, doc->md.opaque);
doc->md.link(ob, link_url, NULL, link_text, doc->md.opaque);
doc->md.normal_text(link_text, link, &doc->data);
doc->md.link(ob, link_text, link_url, NULL, &doc->data);
popbuf(doc, BUFFER_SPAN);
} else {
doc->md.link(ob, link_url, NULL, link, doc->md.opaque);
doc->md.link(ob, link, link_url, NULL, &doc->data);
}
popbuf(doc, BUFFER_SPAN);
}
@ -1021,7 +1021,7 @@ char_autolink_email(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, si
if ((link_len = hoedown_autolink__email(&rewind, link, data, offset, size, 0)) > 0) {
ob->size -= rewind;
doc->md.autolink(ob, link, HOEDOWN_AUTOLINK_EMAIL, doc->md.opaque);
doc->md.autolink(ob, link, HOEDOWN_AUTOLINK_EMAIL, &doc->data);
}
popbuf(doc, BUFFER_SPAN);
@ -1041,7 +1041,7 @@ char_autolink_url(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size
if ((link_len = hoedown_autolink__url(&rewind, link, data, offset, size, 0)) > 0) {
ob->size -= rewind;
doc->md.autolink(ob, link, HOEDOWN_AUTOLINK_NORMAL, doc->md.opaque);
doc->md.autolink(ob, link, HOEDOWN_AUTOLINK_NORMAL, &doc->data);
}
popbuf(doc, BUFFER_SPAN);
@ -1096,7 +1096,7 @@ char_link(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offse
/* render */
if (doc->md.footnote_ref)
ret = doc->md.footnote_ref(ob, fr->num, doc->md.opaque);
ret = doc->md.footnote_ref(ob, fr->num, &doc->data);
}
goto cleanup;
@ -1261,9 +1261,9 @@ char_link(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t offse
if (ob->size && ob->data[ob->size - 1] == '!')
ob->size -= 1;
ret = doc->md.image(ob, u_link, title, content, doc->md.opaque);
ret = doc->md.image(ob, u_link, title, content, &doc->data);
} else {
ret = doc->md.link(ob, u_link, title, content, doc->md.opaque);
ret = doc->md.link(ob, content, u_link, title, &doc->data);
}
/* cleanup */
@ -1302,7 +1302,7 @@ char_superscript(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_
sup = newbuf(doc, BUFFER_SPAN);
parse_inline(sup, doc, data + sup_start, sup_len - sup_start);
doc->md.superscript(ob, sup, doc->md.opaque);
doc->md.superscript(ob, sup, &doc->data);
popbuf(doc, BUFFER_SPAN);
return (sup_start == 2) ? sup_len + 1 : sup_len;
@ -1606,7 +1606,7 @@ parse_blockquote(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_
parse_block(out, doc, work_data, work_size);
if (doc->md.blockquote)
doc->md.blockquote(ob, out, doc->md.opaque);
doc->md.blockquote(ob, out, &doc->data);
popbuf(doc, BUFFER_BLOCK);
return end;
}
@ -1649,7 +1649,7 @@ parse_paragraph(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
hoedown_buffer *tmp = newbuf(doc, BUFFER_BLOCK);
parse_inline(tmp, doc, work.data, work.size);
if (doc->md.paragraph)
doc->md.paragraph(ob, tmp, doc->md.opaque);
doc->md.paragraph(ob, tmp, &doc->data);
popbuf(doc, BUFFER_BLOCK);
} else {
hoedown_buffer *header_work;
@ -1671,7 +1671,7 @@ parse_paragraph(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
parse_inline(tmp, doc, work.data, work.size);
if (doc->md.paragraph)
doc->md.paragraph(ob, tmp, doc->md.opaque);
doc->md.paragraph(ob, tmp, &doc->data);
popbuf(doc, BUFFER_BLOCK);
work.data += beg;
@ -1684,7 +1684,7 @@ parse_paragraph(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
parse_inline(header_work, doc, work.data, work.size);
if (doc->md.header)
doc->md.header(ob, header_work, (int)level, doc->md.opaque);
doc->md.header(ob, header_work, (int)level, &doc->data);
popbuf(doc, BUFFER_SPAN);
}
@ -1725,7 +1725,7 @@ parse_fencedcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_
text.size = line_start - text_start;
if (doc->md.blockcode)
doc->md.blockcode(ob, text.size ? &text : NULL, lang.size ? &lang : NULL, doc->md.opaque);
doc->md.blockcode(ob, text.size ? &text : NULL, lang.size ? &lang : NULL, &doc->data);
return i;
}
@ -1765,7 +1765,7 @@ parse_blockcode(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
hoedown_buffer_putc(work, '\n');
if (doc->md.blockcode)
doc->md.blockcode(ob, work, NULL, doc->md.opaque);
doc->md.blockcode(ob, work, NULL, &doc->data);
popbuf(doc, BUFFER_BLOCK);
return beg;
@ -1901,7 +1901,7 @@ parse_listitem(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
/* render of li itself */
if (doc->md.listitem)
doc->md.listitem(ob, inter, *flags, doc->md.opaque);
doc->md.listitem(ob, inter, *flags, &doc->data);
popbuf(doc, BUFFER_SPAN);
popbuf(doc, BUFFER_SPAN);
@ -1927,7 +1927,7 @@ parse_list(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t size
}
if (doc->md.list)
doc->md.list(ob, work, flags, doc->md.opaque);
doc->md.list(ob, work, flags, &doc->data);
popbuf(doc, BUFFER_BLOCK);
return i;
}
@ -1959,7 +1959,7 @@ parse_atxheader(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
parse_inline(work, doc, data + i, end - i);
if (doc->md.header)
doc->md.header(ob, work, (int)level, doc->md.opaque);
doc->md.header(ob, work, (int)level, &doc->data);
popbuf(doc, BUFFER_SPAN);
}
@ -1977,7 +1977,7 @@ parse_footnote_def(hoedown_buffer *ob, hoedown_document *doc, unsigned int num,
parse_block(work, doc, data, size);
if (doc->md.footnote_def)
doc->md.footnote_def(ob, work, num, doc->md.opaque);
doc->md.footnote_def(ob, work, num, &doc->data);
popbuf(doc, BUFFER_SPAN);
}
@ -2002,7 +2002,7 @@ parse_footnote_list(hoedown_buffer *ob, hoedown_document *doc, struct footnote_l
}
if (doc->md.footnotes)
doc->md.footnotes(ob, work, doc->md.opaque);
doc->md.footnotes(ob, work, &doc->data);
popbuf(doc, BUFFER_BLOCK);
}
@ -2120,7 +2120,7 @@ parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
if (j) {
work.size = i + j;
if (do_render && doc->md.blockhtml)
doc->md.blockhtml(ob, &work, doc->md.opaque);
doc->md.blockhtml(ob, &work, &doc->data);
return work.size;
}
}
@ -2137,7 +2137,7 @@ parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
if (j) {
work.size = i + j;
if (do_render && doc->md.blockhtml)
doc->md.blockhtml(ob, &work, doc->md.opaque);
doc->md.blockhtml(ob, &work, &doc->data);
return work.size;
}
}
@ -2162,7 +2162,7 @@ parse_htmlblock(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t
/* the end of the block has been found */
work.size = tag_end;
if (do_render && doc->md.blockhtml)
doc->md.blockhtml(ob, &work, doc->md.opaque);
doc->md.blockhtml(ob, &work, &doc->data);
return tag_end;
}
@ -2208,7 +2208,7 @@ parse_table_row(
cell_end--;
parse_inline(cell_work, doc, data + cell_start, 1 + cell_end - cell_start);
doc->md.table_cell(row_work, cell_work, col_data[col] | header_flag, doc->md.opaque);
doc->md.table_cell(row_work, cell_work, col_data[col] | header_flag, &doc->data);
popbuf(doc, BUFFER_SPAN);
i++;
@ -2216,10 +2216,10 @@ parse_table_row(
for (; col < columns; ++col) {
hoedown_buffer empty_cell = { 0, 0, 0, 0, NULL, NULL, NULL };
doc->md.table_cell(row_work, &empty_cell, col_data[col] | header_flag, doc->md.opaque);
doc->md.table_cell(row_work, &empty_cell, col_data[col] | header_flag, &doc->data);
}
doc->md.table_row(ob, row_work, doc->md.opaque);
doc->md.table_row(ob, row_work, &doc->data);
popbuf(doc, BUFFER_SPAN);
}
@ -2325,12 +2325,14 @@ parse_table(
{
size_t i;
hoedown_buffer *work = 0;
hoedown_buffer *header_work = 0;
hoedown_buffer *body_work = 0;
size_t columns;
hoedown_table_flags *col_data = NULL;
work = newbuf(doc, BUFFER_BLOCK);
header_work = newbuf(doc, BUFFER_SPAN);
body_work = newbuf(doc, BUFFER_BLOCK);
@ -2364,13 +2366,20 @@ parse_table(
i++;
}
if (doc->md.table_header)
doc->md.table_header(work, header_work, &doc->data);
if (doc->md.table_body)
doc->md.table_body(work, body_work, &doc->data);
if (doc->md.table)
doc->md.table(ob, header_work, body_work, doc->md.opaque);
doc->md.table(ob, work, &doc->data);
}
free(col_data);
popbuf(doc, BUFFER_SPAN);
popbuf(doc, BUFFER_BLOCK);
popbuf(doc, BUFFER_BLOCK);
return i;
}
@ -2402,7 +2411,7 @@ parse_block(hoedown_buffer *ob, hoedown_document *doc, uint8_t *data, size_t siz
else if (is_hrule(txt_data, end)) {
if (doc->md.hrule)
doc->md.hrule(ob, doc->md.opaque);
doc->md.hrule(ob, &doc->data);
while (beg < size && data[beg] != '\n')
beg++;
@ -2702,6 +2711,8 @@ hoedown_document_new(
doc = hoedown_malloc(sizeof(hoedown_document));
memcpy(&doc->md, renderer, sizeof(hoedown_renderer));
doc->data.opaque = renderer->opaque;
hoedown_stack_init(&doc->work_bufs[BUFFER_BLOCK], 4);
hoedown_stack_init(&doc->work_bufs[BUFFER_SPAN], 8);
@ -2815,7 +2826,7 @@ hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t
/* second pass: actual rendering */
if (doc->md.doc_header)
doc->md.doc_header(ob, doc->md.opaque);
doc->md.doc_header(ob, 0, &doc->data);
if (text->size) {
/* adding a final newline if not already present */
@ -2830,7 +2841,7 @@ hoedown_document_render(hoedown_document *doc, hoedown_buffer *ob, const uint8_t
parse_footnote_list(ob, doc, &doc->footnotes_used);
if (doc->md.doc_footer)
doc->md.doc_footer(ob, doc->md.opaque);
doc->md.doc_footer(ob, 0, &doc->data);
/* clean-up */
hoedown_buffer_free(text);
@ -2875,8 +2886,15 @@ hoedown_document_render_inline(hoedown_document *doc, hoedown_buffer *ob, const
/* second pass: actual rendering */
hoedown_buffer_grow(ob, text->size + (text->size >> 1));
if (doc->md.doc_header)
doc->md.doc_header(ob, 1, &doc->data);
parse_inline(ob, doc, text->data, text->size);
if (doc->md.doc_footer)
doc->md.doc_footer(ob, 1, &doc->data);
/* clean-up */
hoedown_buffer_free(text);

View file

@ -85,57 +85,64 @@ typedef enum hoedown_autolink_type {
* TYPES *
*********/
struct hoedown_document;
typedef struct hoedown_document hoedown_document;
struct hoedown_renderer_data {
void *opaque;
};
typedef struct hoedown_renderer_data hoedown_renderer_data;
/* hoedown_renderer - functions for rendering parsed data */
struct hoedown_renderer {
/* state object */
void *opaque;
/* block level callbacks - NULL skips the block */
void (*blockcode)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, void *opaque);
void (*blockquote)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque);
void (*blockhtml)(hoedown_buffer *ob,const hoedown_buffer *text, void *opaque);
void (*header)(hoedown_buffer *ob, const hoedown_buffer *text, int level, void *opaque);
void (*hrule)(hoedown_buffer *ob, void *opaque);
void (*list)(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_list_flags flags, void *opaque);
void (*listitem)(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_list_flags flags, void *opaque);
void (*paragraph)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque);
void (*table)(hoedown_buffer *ob, const hoedown_buffer *header, const hoedown_buffer *body, void *opaque);
void (*table_row)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque);
void (*table_cell)(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_table_flags flags, void *opaque);
void (*footnotes)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque);
void (*footnote_def)(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int num, void *opaque);
void (*blockcode)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data);
void (*blockquote)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
void (*header)(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data);
void (*hrule)(hoedown_buffer *ob, const hoedown_renderer_data *data);
void (*list)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data);
void (*listitem)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data);
void (*paragraph)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
void (*table)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
void (*table_header)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
void (*table_body)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
void (*table_row)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
void (*table_cell)(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data);
void (*footnotes)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
void (*footnote_def)(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data);
void (*blockhtml)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
/* span level callbacks - NULL or return 0 prints the span verbatim */
int (*autolink)(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, void *opaque);
int (*codespan)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque);
int (*double_emphasis)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque);
int (*emphasis)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque);
int (*underline)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque);
int (*highlight)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque);
int (*quote)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque);
int (*image)(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, void *opaque);
int (*linebreak)(hoedown_buffer *ob, void *opaque);
int (*link)(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *content, void *opaque);
int (*raw_html_tag)(hoedown_buffer *ob, const hoedown_buffer *tag, void *opaque);
int (*triple_emphasis)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque);
int (*strikethrough)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque);
int (*superscript)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque);
int (*footnote_ref)(hoedown_buffer *ob, unsigned int num, void *opaque);
int (*math)(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, void *opaque);
int (*autolink)(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data);
int (*codespan)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
int (*double_emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
int (*emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
int (*underline)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
int (*highlight)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
int (*quote)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
int (*image)(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data);
int (*linebreak)(hoedown_buffer *ob, const hoedown_renderer_data *data);
int (*link)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data);
int (*triple_emphasis)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
int (*strikethrough)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
int (*superscript)(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data);
int (*footnote_ref)(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data);
int (*math)(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data);
int (*raw_html)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
/* low level callbacks - NULL copies input directly into the output */
void (*entity)(hoedown_buffer *ob, const hoedown_buffer *entity, void *opaque);
void (*normal_text)(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque);
void (*entity)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
void (*normal_text)(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data);
/* header and footer */
void (*doc_header)(hoedown_buffer *ob, void *opaque);
void (*doc_footer)(hoedown_buffer *ob, void *opaque);
/* miscellaneous callbacks */
void (*doc_header)(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data);
void (*doc_footer)(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data);
};
typedef struct hoedown_renderer hoedown_renderer;
struct hoedown_document;
typedef struct hoedown_document hoedown_document;
/*************
* FUNCTIONS *

View file

@ -56,9 +56,9 @@ static inline void escape_href(hoedown_buffer *ob, const uint8_t *source, size_t
* GENERIC RENDERER *
********************/
static int
rndr_autolink(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, void *opaque)
rndr_autolink(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_type type, const hoedown_renderer_data *data)
{
hoedown_html_renderer_state *state = opaque;
hoedown_html_renderer_state *state = data->opaque;
if (!link || !link->size)
return 0;
@ -70,7 +70,7 @@ rndr_autolink(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_t
if (state->link_attributes) {
hoedown_buffer_putc(ob, '\"');
state->link_attributes(ob, link, opaque);
state->link_attributes(ob, link, data);
hoedown_buffer_putc(ob, '>');
} else {
HOEDOWN_BUFPUTSL(ob, "\">");
@ -93,7 +93,7 @@ rndr_autolink(hoedown_buffer *ob, const hoedown_buffer *link, hoedown_autolink_t
}
static void
rndr_blockcode(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, void *opaque)
rndr_blockcode(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buffer *lang, const hoedown_renderer_data *data)
{
if (ob->size) hoedown_buffer_putc(ob, '\n');
@ -112,16 +112,16 @@ rndr_blockcode(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_buf
}
static void
rndr_blockquote(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_blockquote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
if (ob->size) hoedown_buffer_putc(ob, '\n');
HOEDOWN_BUFPUTSL(ob, "<blockquote>\n");
if (text) hoedown_buffer_put(ob, text->data, text->size);
if (content) hoedown_buffer_put(ob, content->data, content->size);
HOEDOWN_BUFPUTSL(ob, "</blockquote>\n");
}
static int
rndr_codespan(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_codespan(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)
{
HOEDOWN_BUFPUTSL(ob, "<code>");
if (text) escape_html(ob, text->data, text->size);
@ -130,91 +130,91 @@ rndr_codespan(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
}
static int
rndr_strikethrough(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_strikethrough(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
if (!text || !text->size)
if (!content || !content->size)
return 0;
HOEDOWN_BUFPUTSL(ob, "<del>");
hoedown_buffer_put(ob, text->data, text->size);
hoedown_buffer_put(ob, content->data, content->size);
HOEDOWN_BUFPUTSL(ob, "</del>");
return 1;
}
static int
rndr_double_emphasis(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_double_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
if (!text || !text->size)
if (!content || !content->size)
return 0;
HOEDOWN_BUFPUTSL(ob, "<strong>");
hoedown_buffer_put(ob, text->data, text->size);
hoedown_buffer_put(ob, content->data, content->size);
HOEDOWN_BUFPUTSL(ob, "</strong>");
return 1;
}
static int
rndr_emphasis(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
if (!text || !text->size) return 0;
if (!content || !content->size) return 0;
HOEDOWN_BUFPUTSL(ob, "<em>");
if (text) hoedown_buffer_put(ob, text->data, text->size);
if (content) hoedown_buffer_put(ob, content->data, content->size);
HOEDOWN_BUFPUTSL(ob, "</em>");
return 1;
}
static int
rndr_underline(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_underline(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
if (!text || !text->size)
if (!content || !content->size)
return 0;
HOEDOWN_BUFPUTSL(ob, "<u>");
hoedown_buffer_put(ob, text->data, text->size);
hoedown_buffer_put(ob, content->data, content->size);
HOEDOWN_BUFPUTSL(ob, "</u>");
return 1;
}
static int
rndr_highlight(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_highlight(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
if (!text || !text->size)
if (!content || !content->size)
return 0;
HOEDOWN_BUFPUTSL(ob, "<mark>");
hoedown_buffer_put(ob, text->data, text->size);
hoedown_buffer_put(ob, content->data, content->size);
HOEDOWN_BUFPUTSL(ob, "</mark>");
return 1;
}
static int
rndr_quote(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_quote(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
if (!text || !text->size)
if (!content || !content->size)
return 0;
HOEDOWN_BUFPUTSL(ob, "<q>");
hoedown_buffer_put(ob, text->data, text->size);
hoedown_buffer_put(ob, content->data, content->size);
HOEDOWN_BUFPUTSL(ob, "</q>");
return 1;
}
static int
rndr_linebreak(hoedown_buffer *ob, void *opaque)
rndr_linebreak(hoedown_buffer *ob, const hoedown_renderer_data *data)
{
hoedown_html_renderer_state *state = opaque;
hoedown_html_renderer_state *state = data->opaque;
hoedown_buffer_puts(ob, USE_XHTML(state) ? "<br/>\n" : "<br>\n");
return 1;
}
static void
rndr_header(hoedown_buffer *ob, const hoedown_buffer *text, int level, void *opaque)
rndr_header(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data)
{
hoedown_html_renderer_state *state = opaque;
hoedown_html_renderer_state *state = data->opaque;
if (ob->size)
hoedown_buffer_putc(ob, '\n');
@ -224,14 +224,14 @@ rndr_header(hoedown_buffer *ob, const hoedown_buffer *text, int level, void *opa
else
hoedown_buffer_printf(ob, "<h%d>", level);
if (text) hoedown_buffer_put(ob, text->data, text->size);
if (content) hoedown_buffer_put(ob, content->data, content->size);
hoedown_buffer_printf(ob, "</h%d>\n", level);
}
static int
rndr_link(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *content, void *opaque)
rndr_link(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data)
{
hoedown_html_renderer_state *state = opaque;
hoedown_html_renderer_state *state = data->opaque;
HOEDOWN_BUFPUTSL(ob, "<a href=\"");
@ -245,7 +245,7 @@ rndr_link(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *
if (state->link_attributes) {
hoedown_buffer_putc(ob, '\"');
state->link_attributes(ob, link, opaque);
state->link_attributes(ob, link, data);
hoedown_buffer_putc(ob, '>');
} else {
HOEDOWN_BUFPUTSL(ob, "\">");
@ -257,73 +257,73 @@ rndr_link(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *
}
static void
rndr_list(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_list_flags flags, void *opaque)
rndr_list(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data)
{
if (ob->size) hoedown_buffer_putc(ob, '\n');
hoedown_buffer_put(ob, (const uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "<ol>\n" : "<ul>\n"), 5);
if (text) hoedown_buffer_put(ob, text->data, text->size);
if (content) hoedown_buffer_put(ob, content->data, content->size);
hoedown_buffer_put(ob, (const uint8_t *)(flags & HOEDOWN_LIST_ORDERED ? "</ol>\n" : "</ul>\n"), 6);
}
static void
rndr_listitem(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_list_flags flags, void *opaque)
rndr_listitem(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_list_flags flags, const hoedown_renderer_data *data)
{
HOEDOWN_BUFPUTSL(ob, "<li>");
if (text) {
size_t size = text->size;
while (size && text->data[size - 1] == '\n')
if (content) {
size_t size = content->size;
while (size && content->data[size - 1] == '\n')
size--;
hoedown_buffer_put(ob, text->data, size);
hoedown_buffer_put(ob, content->data, size);
}
HOEDOWN_BUFPUTSL(ob, "</li>\n");
}
static void
rndr_paragraph(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_paragraph(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
hoedown_html_renderer_state *state = opaque;
hoedown_html_renderer_state *state = data->opaque;
size_t i = 0;
if (ob->size) hoedown_buffer_putc(ob, '\n');
if (!text || !text->size)
if (!content || !content->size)
return;
while (i < text->size && isspace(text->data[i])) i++;
while (i < content->size && isspace(content->data[i])) i++;
if (i == text->size)
if (i == content->size)
return;
HOEDOWN_BUFPUTSL(ob, "<p>");
if (state->flags & HOEDOWN_HTML_HARD_WRAP) {
size_t org;
while (i < text->size) {
while (i < content->size) {
org = i;
while (i < text->size && text->data[i] != '\n')
while (i < content->size && content->data[i] != '\n')
i++;
if (i > org)
hoedown_buffer_put(ob, text->data + org, i - org);
hoedown_buffer_put(ob, content->data + org, i - org);
/*
* do not insert a line break if this newline
* is the last character on the paragraph
*/
if (i >= text->size - 1)
if (i >= content->size - 1)
break;
rndr_linebreak(ob, opaque);
rndr_linebreak(ob, data);
i++;
}
} else {
hoedown_buffer_put(ob, &text->data[i], text->size - i);
hoedown_buffer_put(ob, content->data + i, content->size - i);
}
HOEDOWN_BUFPUTSL(ob, "</p>\n");
}
static void
rndr_raw_block(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_raw_block(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)
{
size_t org, sz;
if (!text) return;
@ -340,27 +340,27 @@ rndr_raw_block(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
}
static int
rndr_triple_emphasis(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_triple_emphasis(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
if (!text || !text->size) return 0;
if (!content || !content->size) return 0;
HOEDOWN_BUFPUTSL(ob, "<strong><em>");
hoedown_buffer_put(ob, text->data, text->size);
hoedown_buffer_put(ob, content->data, content->size);
HOEDOWN_BUFPUTSL(ob, "</em></strong>");
return 1;
}
static void
rndr_hrule(hoedown_buffer *ob, void *opaque)
rndr_hrule(hoedown_buffer *ob, const hoedown_renderer_data *data)
{
hoedown_html_renderer_state *state = opaque;
hoedown_html_renderer_state *state = data->opaque;
if (ob->size) hoedown_buffer_putc(ob, '\n');
hoedown_buffer_puts(ob, USE_XHTML(state) ? "<hr/>\n" : "<hr>\n");
}
static int
rndr_image(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, void *opaque)
rndr_image(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *alt, const hoedown_renderer_data *data)
{
hoedown_html_renderer_state *state = opaque;
hoedown_html_renderer_state *state = data->opaque;
if (!link || !link->size) return 0;
HOEDOWN_BUFPUTSL(ob, "<img src=\"");
@ -379,9 +379,9 @@ rndr_image(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer
}
static int
rndr_raw_html(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_raw_html(hoedown_buffer *ob, const hoedown_buffer *text, const hoedown_renderer_data *data)
{
hoedown_html_renderer_state *state = opaque;
hoedown_html_renderer_state *state = data->opaque;
/* ESCAPE overrides SKIP_HTML. It doesn't look to see if
* there are any valid tags, just escapes all of them. */
@ -398,29 +398,42 @@ rndr_raw_html(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
}
static void
rndr_table(hoedown_buffer *ob, const hoedown_buffer *header, const hoedown_buffer *body, void *opaque)
rndr_table(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
if (ob->size) hoedown_buffer_putc(ob, '\n');
HOEDOWN_BUFPUTSL(ob, "<table><thead>\n");
if (header)
hoedown_buffer_put(ob, header->data, header->size);
HOEDOWN_BUFPUTSL(ob, "</thead><tbody>\n");
if (body)
hoedown_buffer_put(ob, body->data, body->size);
HOEDOWN_BUFPUTSL(ob, "</tbody></table>\n");
if (ob->size) hoedown_buffer_putc(ob, '\n');
HOEDOWN_BUFPUTSL(ob, "<table>\n");
hoedown_buffer_put(ob, content->data, content->size);
HOEDOWN_BUFPUTSL(ob, "</table>\n");
}
static void
rndr_tablerow(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_table_header(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
if (ob->size) hoedown_buffer_putc(ob, '\n');
HOEDOWN_BUFPUTSL(ob, "<thead>\n");
hoedown_buffer_put(ob, content->data, content->size);
HOEDOWN_BUFPUTSL(ob, "</thead>\n");
}
static void
rndr_table_body(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
if (ob->size) hoedown_buffer_putc(ob, '\n');
HOEDOWN_BUFPUTSL(ob, "<tbody>\n");
hoedown_buffer_put(ob, content->data, content->size);
HOEDOWN_BUFPUTSL(ob, "</tbody>\n");
}
static void
rndr_tablerow(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
HOEDOWN_BUFPUTSL(ob, "<tr>\n");
if (text)
hoedown_buffer_put(ob, text->data, text->size);
if (content) hoedown_buffer_put(ob, content->data, content->size);
HOEDOWN_BUFPUTSL(ob, "</tr>\n");
}
static void
rndr_tablecell(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_table_flags flags, void *opaque)
rndr_tablecell(hoedown_buffer *ob, const hoedown_buffer *content, hoedown_table_flags flags, const hoedown_renderer_data *data)
{
if (flags & HOEDOWN_TABLE_HEADER) {
HOEDOWN_BUFPUTSL(ob, "<th");
@ -445,8 +458,8 @@ rndr_tablecell(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_table_fla
HOEDOWN_BUFPUTSL(ob, ">");
}
if (text)
hoedown_buffer_put(ob, text->data, text->size);
if (content)
hoedown_buffer_put(ob, content->data, content->size);
if (flags & HOEDOWN_TABLE_HEADER) {
HOEDOWN_BUFPUTSL(ob, "</th>\n");
@ -456,51 +469,50 @@ rndr_tablecell(hoedown_buffer *ob, const hoedown_buffer *text, hoedown_table_fla
}
static int
rndr_superscript(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_superscript(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
if (!text || !text->size) return 0;
if (!content || !content->size) return 0;
HOEDOWN_BUFPUTSL(ob, "<sup>");
hoedown_buffer_put(ob, text->data, text->size);
hoedown_buffer_put(ob, content->data, content->size);
HOEDOWN_BUFPUTSL(ob, "</sup>");
return 1;
}
static void
rndr_normal_text(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_normal_text(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
if (text)
escape_html(ob, text->data, text->size);
if (content)
escape_html(ob, content->data, content->size);
}
static void
rndr_footnotes(hoedown_buffer *ob, const hoedown_buffer *text, void *opaque)
rndr_footnotes(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_renderer_data *data)
{
hoedown_html_renderer_state *state = opaque;
hoedown_html_renderer_state *state = data->opaque;
if (ob->size) hoedown_buffer_putc(ob, '\n');
HOEDOWN_BUFPUTSL(ob, "<div class=\"footnotes\">\n");
hoedown_buffer_puts(ob, USE_XHTML(state) ? "<hr/>\n" : "<hr>\n");
HOEDOWN_BUFPUTSL(ob, "<ol>\n");
if (text)
hoedown_buffer_put(ob, text->data, text->size);
if (content) hoedown_buffer_put(ob, content->data, content->size);
HOEDOWN_BUFPUTSL(ob, "\n</ol>\n</div>\n");
}
static void
rndr_footnote_def(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int num, void *opaque)
rndr_footnote_def(hoedown_buffer *ob, const hoedown_buffer *content, unsigned int num, const hoedown_renderer_data *data)
{
size_t i = 0;
int pfound = 0;
/* insert anchor at the end of first paragraph block */
if (text) {
while ((i+3) < text->size) {
if (text->data[i++] != '<') continue;
if (text->data[i++] != '/') continue;
if (text->data[i++] != 'p' && text->data[i] != 'P') continue;
if (text->data[i] != '>') continue;
if (content) {
while ((i+3) < content->size) {
if (content->data[i++] != '<') continue;
if (content->data[i++] != '/') continue;
if (content->data[i++] != 'p' && content->data[i] != 'P') continue;
if (content->data[i] != '>') continue;
i -= 3;
pfound = 1;
break;
@ -509,24 +521,24 @@ rndr_footnote_def(hoedown_buffer *ob, const hoedown_buffer *text, unsigned int n
hoedown_buffer_printf(ob, "\n<li id=\"fn%d\">\n", num);
if (pfound) {
hoedown_buffer_put(ob, text->data, i);
hoedown_buffer_put(ob, content->data, i);
hoedown_buffer_printf(ob, "&nbsp;<a href=\"#fnref%d\" rev=\"footnote\">&#8617;</a>", num);
hoedown_buffer_put(ob, text->data + i, text->size - i);
} else if (text) {
hoedown_buffer_put(ob, text->data, text->size);
hoedown_buffer_put(ob, content->data + i, content->size - i);
} else if (content) {
hoedown_buffer_put(ob, content->data, content->size);
}
HOEDOWN_BUFPUTSL(ob, "</li>\n");
}
static int
rndr_footnote_ref(hoedown_buffer *ob, unsigned int num, void *opaque)
rndr_footnote_ref(hoedown_buffer *ob, unsigned int num, const hoedown_renderer_data *data)
{
hoedown_buffer_printf(ob, "<sup id=\"fnref%d\"><a href=\"#fn%d\" rel=\"footnote\">%d</a></sup>", num, num, num);
return 1;
}
static int
rndr_math(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, void *opaque)
rndr_math(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, const hoedown_renderer_data *data)
{
hoedown_buffer_put(ob, (const uint8_t *)(displaymode ? "\\[" : "\\("), 2);
escape_html(ob, text->data, text->size);
@ -535,9 +547,9 @@ rndr_math(hoedown_buffer *ob, const hoedown_buffer *text, int displaymode, void
}
static void
toc_header(hoedown_buffer *ob, const hoedown_buffer *text, int level, void *opaque)
toc_header(hoedown_buffer *ob, const hoedown_buffer *content, int level, const hoedown_renderer_data *data)
{
hoedown_html_renderer_state *state = opaque;
hoedown_html_renderer_state *state = data->opaque;
if (level <= state->toc_data.nesting_level) {
/* set the level offset if this is the first header
@ -564,23 +576,23 @@ toc_header(hoedown_buffer *ob, const hoedown_buffer *text, int level, void *opaq
}
hoedown_buffer_printf(ob, "<a href=\"#toc_%d\">", state->toc_data.header_count++);
if (text) escape_html(ob, text->data, text->size);
if (content) escape_html(ob, content->data, content->size);
HOEDOWN_BUFPUTSL(ob, "</a>\n");
}
}
static int
toc_link(hoedown_buffer *ob, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_buffer *content, void *opaque)
toc_link(hoedown_buffer *ob, const hoedown_buffer *content, const hoedown_buffer *link, const hoedown_buffer *title, const hoedown_renderer_data *data)
{
if (content && content->size)
hoedown_buffer_put(ob, content->data, content->size);
if (content && content->size) hoedown_buffer_put(ob, content->data, content->size);
return 1;
}
static void
toc_finalize(hoedown_buffer *ob, void *opaque)
toc_finalize(hoedown_buffer *ob, int inline_render, const hoedown_renderer_data *data)
{
hoedown_html_renderer_state *state = opaque;
if (inline_render) return;
hoedown_html_renderer_state *state = data->opaque;
while (state->toc_data.current_level > 0) {
HOEDOWN_BUFPUTSL(ob, "</li>\n</ul>\n");
@ -594,7 +606,6 @@ hoedown_html_toc_renderer_new(int nesting_level)
static const hoedown_renderer cb_default = {
NULL,
NULL,
NULL,
NULL,
toc_header,
@ -607,6 +618,9 @@ hoedown_html_toc_renderer_new(int nesting_level)
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
rndr_codespan,
@ -618,12 +632,12 @@ hoedown_html_toc_renderer_new(int nesting_level)
NULL,
NULL,
toc_link,
NULL,
rndr_triple_emphasis,
rndr_strikethrough,
rndr_superscript,
NULL,
NULL,
NULL,
NULL,
NULL,
@ -657,17 +671,19 @@ hoedown_html_renderer_new(hoedown_html_flags render_flags, int nesting_level)
rndr_blockcode,
rndr_blockquote,
rndr_raw_block,
rndr_header,
rndr_hrule,
rndr_list,
rndr_listitem,
rndr_paragraph,
rndr_table,
rndr_table_header,
rndr_table_body,
rndr_tablerow,
rndr_tablecell,
rndr_footnotes,
rndr_footnote_def,
rndr_raw_block,
rndr_autolink,
rndr_codespan,
@ -679,12 +695,12 @@ hoedown_html_renderer_new(hoedown_html_flags render_flags, int nesting_level)
rndr_image,
rndr_linebreak,
rndr_link,
rndr_raw_html,
rndr_triple_emphasis,
rndr_strikethrough,
rndr_superscript,
rndr_footnote_ref,
rndr_math,
rndr_raw_html,
NULL,
rndr_normal_text,

View file

@ -46,7 +46,7 @@ struct hoedown_html_renderer_state {
hoedown_html_flags flags;
/* extra callbacks */
void (*link_attributes)(hoedown_buffer *ob, const hoedown_buffer *url, void *self);
void (*link_attributes)(hoedown_buffer *ob, const hoedown_buffer *url, const hoedown_renderer_data *data);
};
typedef struct hoedown_html_renderer_state hoedown_html_renderer_state;