ext/xhtml.c in redcarpet-1.3.3 vs ext/xhtml.c in redcarpet-1.5.0
- old
+ new
@@ -20,13 +20,17 @@
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
-struct toc_data {
- int header_count;
- int current_level;
+struct xhtml_renderopt {
+ struct {
+ int header_count;
+ int current_level;
+ } toc_data;
+
+ unsigned int flags;
};
static int
is_safe_link(const char *link, size_t link_len)
{
@@ -112,88 +116,107 @@
else lus_attr_escape(ob, link, link_size);
BUFPUTSL(ob, "</a>");
}
static int
-rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, struct mkd_renderopt *options)
+rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, void *opaque)
{
+ struct xhtml_renderopt *options = opaque;
+
if (!link || !link->size)
return 0;
- if ((options->flags & RENDER_SAFELINK) != 0 && !is_safe_link(link->data, link->size))
+ if ((options->flags & XHTML_SAFELINK) != 0 && !is_safe_link(link->data, link->size))
return 0;
rndr_autolink2(ob, link->data, link->size, type);
return 1;
}
static void
-rndr_blockcode(struct buf *ob, struct buf *text, struct mkd_renderopt *options)
+rndr_blockcode(struct buf *ob, struct buf *text, void *opaque)
{
if (ob->size) bufputc(ob, '\n');
BUFPUTSL(ob, "<pre><code>");
if (text) lus_attr_escape(ob, text->data, text->size);
BUFPUTSL(ob, "</code></pre>\n");
}
static void
-rndr_blockquote(struct buf *ob, struct buf *text, struct mkd_renderopt *options)
+rndr_blockquote(struct buf *ob, struct buf *text, void *opaque)
{
BUFPUTSL(ob, "<blockquote>\n");
if (text) bufput(ob, text->data, text->size);
BUFPUTSL(ob, "</blockquote>");
}
static int
-rndr_codespan(struct buf *ob, struct buf *text, struct mkd_renderopt *options)
+rndr_codespan(struct buf *ob, struct buf *text, void *opaque)
{
BUFPUTSL(ob, "<code>");
if (text) lus_attr_escape(ob, text->data, text->size);
BUFPUTSL(ob, "</code>");
return 1;
}
static int
-rndr_double_emphasis(struct buf *ob, struct buf *text, char c, struct mkd_renderopt *options)
+rndr_double_emphasis(struct buf *ob, struct buf *text, char c, void *opaque)
{
- if (!text || !text->size) return 0;
- BUFPUTSL(ob, "<strong>");
- bufput(ob, text->data, text->size);
- BUFPUTSL(ob, "</strong>");
+ struct xhtml_renderopt *options = opaque;
+
+ if (!text || !text->size)
+ return 0;
+
+ if (c == '~') {
+ if (options->flags & XHTML_SKIP_STRIKETHROUGH)
+ return 0;
+
+ BUFPUTSL(ob, "<span style=\"text-decoration:line-through;\">");
+ bufput(ob, text->data, text->size);
+ BUFPUTSL(ob, "</span>");
+ } else {
+ BUFPUTSL(ob, "<strong>");
+ bufput(ob, text->data, text->size);
+ BUFPUTSL(ob, "</strong>");
+ }
+
return 1;
}
static int
-rndr_emphasis(struct buf *ob, struct buf *text, char c, struct mkd_renderopt *options)
+rndr_emphasis(struct buf *ob, struct buf *text, char c, void *opaque)
{
- if (!text || !text->size) return 0;
+ if (!text || !text->size || c == '~') return 0;
BUFPUTSL(ob, "<em>");
if (text) bufput(ob, text->data, text->size);
BUFPUTSL(ob, "</em>");
return 1;
}
static void
-rndr_header(struct buf *ob, struct buf *text, int level, struct mkd_renderopt *options)
+rndr_header(struct buf *ob, struct buf *text, int level, void *opaque)
{
+ struct xhtml_renderopt *options = opaque;
+
if (ob->size)
bufputc(ob, '\n');
- if (options->flags & RENDER_TOC) {
- struct toc_data *data = options->opaque;
- bufprintf(ob, "<a name=\"toc_%d\"></a>", data->header_count++);
+ if (options->flags & XHTML_TOC) {
+ bufprintf(ob, "<a name=\"toc_%d\"></a>", options->toc_data.header_count++);
}
bufprintf(ob, "<h%d>", level);
if (text) bufput(ob, text->data, text->size);
bufprintf(ob, "</h%d>\n", level);
}
static int
-rndr_link(struct buf *ob, struct buf *link, struct buf *title, struct buf *content, struct mkd_renderopt *options)
+rndr_link(struct buf *ob, struct buf *link, struct buf *title, struct buf *content, void *opaque)
{
- if ((options->flags & RENDER_SAFELINK) != 0 && !is_safe_link(link->data, link->size))
+ struct xhtml_renderopt *options = opaque;
+
+ if ((options->flags & XHTML_SAFELINK) != 0 && !is_safe_link(link->data, link->size))
return 0;
BUFPUTSL(ob, "<a href=\"");
if (link && link->size) lus_attr_escape(ob, link->data, link->size);
if (title && title->size) {
@@ -204,31 +227,31 @@
BUFPUTSL(ob, "</a>");
return 1;
}
static void
-rndr_list(struct buf *ob, struct buf *text, int flags, struct mkd_renderopt *options)
+rndr_list(struct buf *ob, struct buf *text, int flags, void *opaque)
{
if (ob->size) bufputc(ob, '\n');
bufput(ob, flags & MKD_LIST_ORDERED ? "<ol>\n" : "<ul>\n", 5);
if (text) bufput(ob, text->data, text->size);
bufput(ob, flags & MKD_LIST_ORDERED ? "</ol>\n" : "</ul>\n", 6);
}
static void
-rndr_listitem(struct buf *ob, struct buf *text, int flags, struct mkd_renderopt *options)
+rndr_listitem(struct buf *ob, struct buf *text, int flags, void *opaque)
{
BUFPUTSL(ob, "<li>");
if (text) {
while (text->size && text->data[text->size - 1] == '\n')
text->size -= 1;
bufput(ob, text->data, text->size); }
BUFPUTSL(ob, "</li>\n");
}
static void
-rndr_paragraph(struct buf *ob, struct buf *text, struct mkd_renderopt *options)
+rndr_paragraph(struct buf *ob, struct buf *text, void *opaque)
{
size_t i = 0;
if (ob->size) bufputc(ob, '\n');
@@ -243,11 +266,11 @@
BUFPUTSL(ob, "</p>\n");
}
}
static void
-rndr_raw_block(struct buf *ob, struct buf *text, struct mkd_renderopt *options)
+rndr_raw_block(struct buf *ob, struct buf *text, void *opaque)
{
size_t org, sz;
if (!text) return;
sz = text->size;
while (sz > 0 && text->data[sz - 1] == '\n') sz -= 1;
@@ -258,11 +281,11 @@
bufput(ob, text->data + org, sz - org);
bufputc(ob, '\n');
}
static int
-rndr_triple_emphasis(struct buf *ob, struct buf *text, char c, struct mkd_renderopt *options)
+rndr_triple_emphasis(struct buf *ob, struct buf *text, char c, void *opaque)
{
if (!text || !text->size) return 0;
BUFPUTSL(ob, "<strong><em>");
bufput(ob, text->data, text->size);
BUFPUTSL(ob, "</em></strong>");
@@ -273,18 +296,18 @@
/**********************
* XHTML 1.0 RENDERER *
**********************/
static void
-rndr_hrule(struct buf *ob, struct mkd_renderopt *options)
+rndr_hrule(struct buf *ob, void *opaque)
{
if (ob->size) bufputc(ob, '\n');
BUFPUTSL(ob, "<hr />\n");
}
static int
-rndr_image(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt, struct mkd_renderopt *options)
+rndr_image(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt, void *opaque)
{
if (!link || !link->size) return 0;
BUFPUTSL(ob, "<img src=\"");
lus_attr_escape(ob, link->data, link->size);
BUFPUTSL(ob, "\" alt=\"");
@@ -296,31 +319,32 @@
BUFPUTSL(ob, "\" />");
return 1;
}
static int
-rndr_linebreak(struct buf *ob, struct mkd_renderopt *options)
+rndr_linebreak(struct buf *ob, void *opaque)
{
BUFPUTSL(ob, "<br />\n");
return 1;
}
static int
-rndr_raw_html(struct buf *ob, struct buf *text, struct mkd_renderopt *options)
+rndr_raw_html(struct buf *ob, struct buf *text, void *opaque)
{
+ struct xhtml_renderopt *options = opaque;
int escape_html = 0;
- if (options->flags & RENDER_SKIP_HTML)
+ if (options->flags & XHTML_SKIP_HTML)
escape_html = 1;
- else if ((options->flags & RENDER_SKIP_STYLE) != 0 && is_html_tag(text, "<style>"))
+ else if ((options->flags & XHTML_SKIP_STYLE) != 0 && is_html_tag(text, "<style>"))
escape_html = 1;
- else if ((options->flags & RENDER_SKIP_LINKS) != 0 && is_html_tag(text, "<a>"))
+ else if ((options->flags & XHTML_SKIP_LINKS) != 0 && is_html_tag(text, "<a>"))
escape_html = 1;
- else if ((options->flags & RENDER_SKIP_IMAGES) != 0 && is_html_tag(text, "<img>"))
+ else if ((options->flags & XHTML_SKIP_IMAGES) != 0 && is_html_tag(text, "<img>"))
escape_html = 1;
if (escape_html)
lus_attr_escape(ob, text->data, text->size);
@@ -328,11 +352,60 @@
bufput(ob, text->data, text->size);
return 1;
}
+static void
+rndr_table(struct buf *ob, struct buf *header, struct buf *body, void *opaque)
+{
+ if (ob->size) bufputc(ob, '\n');
+ BUFPUTSL(ob, "<table><thead>\n");
+ if (header)
+ bufput(ob, header->data, header->size);
+ BUFPUTSL(ob, "\n</thead><tbody>\n");
+ if (body)
+ bufput(ob, body->data, body->size);
+ BUFPUTSL(ob, "\n</tbody></table>");
+}
+static void
+rndr_tablerow(struct buf *ob, struct buf *text, void *opaque)
+{
+ if (ob->size) bufputc(ob, '\n');
+ BUFPUTSL(ob, "<tr>\n");
+ if (text)
+ bufput(ob, text->data, text->size);
+ BUFPUTSL(ob, "\n</tr>");
+}
+
+static void
+rndr_tablecell(struct buf *ob, struct buf *text, int align, void *opaque)
+{
+ if (ob->size) bufputc(ob, '\n');
+ switch (align) {
+ case MKD_TABLE_ALIGN_L:
+ BUFPUTSL(ob, "<td align=\"left\">");
+ break;
+
+ case MKD_TABLE_ALIGN_R:
+ BUFPUTSL(ob, "<td align=\"right\">");
+ break;
+
+ case MKD_TABLE_ALIGN_CENTER:
+ BUFPUTSL(ob, "<td align=\"center\">");
+ break;
+
+ default:
+ BUFPUTSL(ob, "<td>");
+ break;
+ }
+
+ if (text)
+ bufput(ob, text->data, text->size);
+ BUFPUTSL(ob, "</td>");
+}
+
static struct {
char c0;
const char *pattern;
const char *entity;
int skip;
@@ -416,17 +489,18 @@
bufputs(ob, ent);
return 1;
}
static void
-rndr_normal_text(struct buf *ob, struct buf *text, struct mkd_renderopt *options)
+rndr_normal_text(struct buf *ob, struct buf *text, void *opaque)
{
size_t i;
int open_single = 0, open_double = 0, open_tag = 0;
+ struct xhtml_renderopt *options = opaque;
- int autolink = (options->flags & RENDER_AUTOLINK);
- int smartypants = (options->flags & RENDER_SMARTYPANTS);
+ int autolink = (options->flags & XHTML_AUTOLINK);
+ int smartypants = (options->flags & XHTML_SMARTYPANTS);
if (!text)
return;
if (!autolink && !smartypants) {
@@ -561,60 +635,63 @@
bufputc(ob, c);
}
}
static void
-toc_header(struct buf *ob, struct buf *text, int level, struct mkd_renderopt *options)
+toc_header(struct buf *ob, struct buf *text, int level, void *opaque)
{
- struct toc_data *data = (struct toc_data *)options->opaque;
+ struct xhtml_renderopt *options = opaque;
- if (level > data->current_level) {
+ if (level > options->toc_data.current_level) {
if (level > 1)
BUFPUTSL(ob, "<li>");
BUFPUTSL(ob, "<ul>\n");
}
- if (level < data->current_level) {
+ if (level < options->toc_data.current_level) {
BUFPUTSL(ob, "</ul>");
- if (data->current_level > 1)
+ if (options->toc_data.current_level > 1)
BUFPUTSL(ob, "</li>\n");
}
- data->current_level = level;
+ options->toc_data.current_level = level;
- bufprintf(ob, "<li><a href=\"#toc_%d\">", data->header_count++);
+ bufprintf(ob, "<li><a href=\"#toc_%d\">", options->toc_data.header_count++);
if (text)
bufput(ob, text->data, text->size);
BUFPUTSL(ob, "</a></li>\n");
}
static void
-toc_finalize(struct buf *ob, struct mkd_renderopt *options)
+toc_finalize(struct buf *ob, void *opaque)
{
- struct toc_data *data = (struct toc_data *)options->opaque;
+ struct xhtml_renderopt *options = opaque;
- while (data->current_level > 1) {
+ while (options->toc_data.current_level > 1) {
BUFPUTSL(ob, "</ul></li>\n");
- data->current_level--;
+ options->toc_data.current_level--;
}
- if (data->current_level)
+ if (options->toc_data.current_level)
BUFPUTSL(ob, "</ul>\n");
}
void
-init_toc_renderer(struct mkd_renderer *renderer, int recursion_depth)
+init_toc_renderer(struct mkd_renderer *renderer)
{
static const struct mkd_renderer toc_render = {
NULL,
NULL,
NULL,
toc_header,
NULL,
NULL,
NULL,
NULL,
+ NULL,
+ NULL,
+ NULL,
rndr_autolink,
rndr_codespan,
rndr_double_emphasis,
rndr_emphasis,
@@ -628,37 +705,37 @@
NULL,
NULL,
toc_finalize,
- NULL,
-
- { 0, 0 },
- { 0, 0 },
+ "*-~",
+ NULL
};
- memcpy(renderer, &toc_render, sizeof(struct mkd_renderer));
+ struct xhtml_renderopt *options;
+ options = calloc(1, sizeof(struct xhtml_renderopt));
+ options->flags = XHTML_TOC;
- renderer->parser_options.recursion_depth = recursion_depth;
- renderer->render_options.flags = RENDER_TOC;
- renderer->render_options.opaque = calloc(1, sizeof(struct toc_data));
+ memcpy(renderer, &toc_render, sizeof(struct mkd_renderer));
+ renderer->opaque = options;
}
void
-init_xhtml_renderer(struct mkd_renderer *renderer,
- unsigned int render_flags,
- unsigned int parser_flags, int recursion_depth)
+init_xhtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags)
{
static const struct mkd_renderer renderer_default = {
rndr_blockcode,
rndr_blockquote,
rndr_raw_block,
rndr_header,
rndr_hrule,
rndr_list,
rndr_listitem,
rndr_paragraph,
+ rndr_table,
+ rndr_tablerow,
+ rndr_tablecell,
rndr_autolink,
rndr_codespan,
rndr_double_emphasis,
rndr_emphasis,
@@ -672,35 +749,31 @@
rndr_normal_text,
NULL,
NULL,
- "*_",
-
- { 0, 0 },
- { 0, 0 },
+ "*_~",
+ NULL
};
+ struct xhtml_renderopt *options;
+ options = calloc(1, sizeof(struct xhtml_renderopt));
+ options->flags = render_flags;
+
memcpy(renderer, &renderer_default, sizeof(struct mkd_renderer));
+ renderer->opaque = options;
- if (render_flags & RENDER_SKIP_IMAGES)
+ if (render_flags & XHTML_SKIP_IMAGES)
renderer->image = NULL;
- if (render_flags & RENDER_SKIP_LINKS) {
+ if (render_flags & XHTML_SKIP_LINKS) {
renderer->link = NULL;
renderer->autolink = NULL;
}
-
- renderer->parser_options.recursion_depth = recursion_depth;
- renderer->parser_options.flags = parser_flags;
-
- renderer->render_options.flags = render_flags;
- if (render_flags & RENDER_TOC)
- renderer->render_options.opaque = calloc(1, sizeof(struct toc_data));
}
void
free_renderer(struct mkd_renderer *renderer)
{
- free(renderer->render_options.opaque);
+ free(renderer->opaque);
}