Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

for now update sundown structure and prepare php-sundown2.

  • Loading branch information...
commit 17a74fd422d3cbbdb85ac7b35f90b181a9ac211f 1 parent d8d92da
@chobie authored
View
181 src/html.c
@@ -23,17 +23,7 @@
#include <stdio.h>
#include <ctype.h>
-struct html_renderopt {
- void *extra;
-
- struct {
- int header_count;
- int current_level;
- } toc_data;
-
- unsigned int flags;
- const char *close_tag;
-};
+#define USE_XHTML(opt) (opt->flags & HTML_USE_XHTML)
static inline void
put_scaped_char(struct buf *ob, char c)
@@ -120,8 +110,15 @@ rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, void *op
BUFPUTSL(ob, "<a href=\"");
if (type == MKDA_EMAIL)
BUFPUTSL(ob, "mailto:");
- bufput(ob, link->data, link->size);
- BUFPUTSL(ob, "\">");
+ sdhtml_escape(ob, link->data, link->size);
+
+ if (options->link_attributes) {
+ bufputc(ob, '\"');
+ options->link_attributes(ob, link, opaque);
+ bufputc(ob, '>');
+ } else {
+ BUFPUTSL(ob, "\">");
+ }
/*
* Pretty printing: if we get an email address as
@@ -223,9 +220,10 @@ rndr_blockcode_github(struct buf *ob, struct buf *text, struct buf *lang, void *
static void
rndr_blockquote(struct buf *ob, struct buf *text, void *opaque)
{
+ if (ob->size) bufputc(ob, '\n');
BUFPUTSL(ob, "<blockquote>\n");
if (text) bufput(ob, text->data, text->size);
- BUFPUTSL(ob, "</blockquote>");
+ BUFPUTSL(ob, "</blockquote>\n");
}
static int
@@ -272,6 +270,14 @@ rndr_emphasis(struct buf *ob, struct buf *text, void *opaque)
return 1;
}
+static int
+rndr_linebreak(struct buf *ob, void *opaque)
+{
+ struct html_renderopt *options = opaque;
+ bufputs(ob, USE_XHTML(options) ? "<br/>\n" : "<br>\n");
+ return 1;
+}
+
static void
rndr_header(struct buf *ob, struct buf *text, int level, void *opaque)
{
@@ -294,15 +300,27 @@ rndr_link(struct buf *ob, struct buf *link, struct buf *title, struct buf *conte
{
struct html_renderopt *options = opaque;
- if ((options->flags & HTML_SAFELINK) != 0 && !sd_autolink_issafe(link->data, link->size))
+ if (link != NULL && (options->flags & HTML_SAFELINK) != 0 && !sd_autolink_issafe(link->data, link->size))
return 0;
BUFPUTSL(ob, "<a href=\"");
- if (link && link->size) bufput(ob, link->data, link->size);
+
+ if (link && link->size)
+ sdhtml_escape(ob, link->data, link->size);
+
if (title && title->size) {
BUFPUTSL(ob, "\" title=\"");
- sdhtml_escape(ob, title->data, title->size); }
- BUFPUTSL(ob, "\">");
+ sdhtml_escape(ob, title->data, title->size);
+ }
+
+ if (options->link_attributes) {
+ bufputc(ob, '\"');
+ options->link_attributes(ob, link, opaque);
+ bufputc(ob, '>');
+ } else {
+ BUFPUTSL(ob, "\">");
+ }
+
if (content && content->size) bufput(ob, content->data, content->size);
BUFPUTSL(ob, "</a>");
return 1;
@@ -355,11 +373,14 @@ rndr_paragraph(struct buf *ob, struct buf *text, void *opaque)
if (i > org)
bufput(ob, text->data + org, i - org);
- if (i >= text->size)
+ /*
+ * do not insert a line break if this newline
+ * is the last character on the paragraph
+ */
+ if (i >= text->size - 1)
break;
-
- BUFPUTSL(ob, "<br");
- bufputs(ob, options->close_tag);
+
+ rndr_linebreak(ob, opaque);
i++;
}
} else {
@@ -398,8 +419,7 @@ rndr_hrule(struct buf *ob, void *opaque)
{
struct html_renderopt *options = opaque;
if (ob->size) bufputc(ob, '\n');
- BUFPUTSL(ob, "<hr");
- bufputs(ob, options->close_tag);
+ bufputs(ob, USE_XHTML(options) ? "<hr/>\n" : "<hr>\n");
}
static int
@@ -416,17 +436,7 @@ rndr_image(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt,
BUFPUTSL(ob, "\" title=\"");
sdhtml_escape(ob, title->data, title->size); }
- bufputc(ob, '"');
- bufputs(ob, options->close_tag);
- return 1;
-}
-
-static int
-rndr_linebreak(struct buf *ob, void *opaque)
-{
- struct html_renderopt *options = opaque;
- BUFPUTSL(ob, "<br");
- bufputs(ob, options->close_tag);
+ bufputs(ob, USE_XHTML(options) ? "\"/>" : "\">");
return 1;
}
@@ -458,47 +468,65 @@ rndr_table(struct buf *ob, struct buf *header, struct buf *body, void *opaque)
BUFPUTSL(ob, "<table><thead>\n");
if (header)
bufput(ob, header->data, header->size);
- BUFPUTSL(ob, "\n</thead><tbody>\n");
+ BUFPUTSL(ob, "</thead><tbody>\n");
if (body)
bufput(ob, body->data, body->size);
- BUFPUTSL(ob, "\n</tbody></table>");
+ BUFPUTSL(ob, "</tbody></table>\n");
}
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>");
+ BUFPUTSL(ob, "</tr>\n");
}
static void
-rndr_tablecell(struct buf *ob, struct buf *text, int align, void *opaque)
+rndr_tablecell(struct buf *ob, struct buf *text, int flags, void *opaque)
{
- if (ob->size) bufputc(ob, '\n');
- switch (align) {
- case MKD_TABLE_ALIGN_L:
- BUFPUTSL(ob, "<td align=\"left\">");
+ if (flags & MKD_TABLE_HEADER) {
+ BUFPUTSL(ob, "<th");
+ } else {
+ BUFPUTSL(ob, "<td");
+ }
+
+ switch (flags & MKD_TABLE_ALIGNMASK) {
+ case MKD_TABLE_ALIGN_CENTER:
+ BUFPUTSL(ob, " align=\"center\">");
break;
- case MKD_TABLE_ALIGN_R:
- BUFPUTSL(ob, "<td align=\"right\">");
+ case MKD_TABLE_ALIGN_L:
+ BUFPUTSL(ob, " align=\"left\">");
break;
- case MKD_TABLE_ALIGN_CENTER:
- BUFPUTSL(ob, "<td align=\"center\">");
+ case MKD_TABLE_ALIGN_R:
+ BUFPUTSL(ob, " align=\"right\">");
break;
default:
- BUFPUTSL(ob, "<td>");
- break;
+ BUFPUTSL(ob, ">");
}
if (text)
bufput(ob, text->data, text->size);
- BUFPUTSL(ob, "</td>");
+
+ if (flags & MKD_TABLE_HEADER) {
+ BUFPUTSL(ob, "</th>\n");
+ } else {
+ BUFPUTSL(ob, "</td>\n");
+ }
+}
+
+static int
+rndr_superscript(struct buf *ob, struct buf *text, void *opaque)
+{
+ if (!text || !text->size) return 0;
+ BUFPUTSL(ob, "<sup>");
+ bufput(ob, text->data, text->size);
+ BUFPUTSL(ob, "</sup>");
+ return 1;
}
static void
@@ -548,9 +576,9 @@ toc_finalize(struct buf *ob, void *opaque)
}
void
-sdhtml_toc_renderer(struct mkd_renderer *renderer, void *extra)
+sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options)
{
- static const struct mkd_renderer toc_render = {
+ static const struct sd_callbacks cb_default = {
NULL,
NULL,
NULL,
@@ -573,32 +601,25 @@ sdhtml_toc_renderer(struct mkd_renderer *renderer, void *extra)
NULL,
rndr_triple_emphasis,
rndr_strikethrough,
+ rndr_superscript,
NULL,
NULL,
NULL,
toc_finalize,
-
- NULL
};
- struct html_renderopt *options;
- options = calloc(1, sizeof(struct html_renderopt));
+ memset(options, 0x0, sizeof(struct html_renderopt));
options->flags = HTML_TOC;
- options->extra = extra;
- memcpy(renderer, &toc_render, sizeof(struct mkd_renderer));
- renderer->opaque = options;
+ memcpy(callbacks, &cb_default, sizeof(struct sd_callbacks));
}
void
-sdhtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags, void *extra)
+sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options, unsigned int render_flags)
{
- static const char *xhtml_close = "/>\n";
- static const char *html_close = ">\n";
-
- static const struct mkd_renderer renderer_default = {
+ static const struct sd_callbacks cb_default = {
rndr_blockcode,
rndr_blockquote,
rndr_raw_block,
@@ -621,43 +642,33 @@ sdhtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags, void *
rndr_raw_html,
rndr_triple_emphasis,
rndr_strikethrough,
+ rndr_superscript,
NULL,
rndr_normal_text,
NULL,
NULL,
-
- NULL
};
- struct html_renderopt *options;
- options = calloc(1, sizeof(struct html_renderopt));
+ /* Prepare the options pointer */
+ memset(options, 0x0, sizeof(struct html_renderopt));
options->flags = render_flags;
- options->close_tag = (render_flags & HTML_USE_XHTML) ? xhtml_close : html_close;
- options->extra = extra;
- memcpy(renderer, &renderer_default, sizeof(struct mkd_renderer));
- renderer->opaque = options;
+ /* Prepare the callbacks */
+ memcpy(callbacks, &cb_default, sizeof(struct sd_callbacks));
if (render_flags & HTML_SKIP_IMAGES)
- renderer->image = NULL;
+ callbacks->image = NULL;
if (render_flags & HTML_SKIP_LINKS) {
- renderer->link = NULL;
- renderer->autolink = NULL;
+ callbacks->link = NULL;
+ callbacks->autolink = NULL;
}
if (render_flags & HTML_SKIP_HTML)
- renderer->blockhtml = NULL;
+ callbacks->blockhtml = NULL;
if (render_flags & HTML_GITHUB_BLOCKCODE)
- renderer->blockcode = rndr_blockcode_github;
+ callbacks->blockcode = rndr_blockcode_github;
}
-
-void
-sdhtml_free_renderer(struct mkd_renderer *renderer)
-{
- free(renderer->opaque);
-}
-
View
21 src/html.h
@@ -21,6 +21,18 @@
#include "buffer.h"
#include <stdlib.h>
+struct html_renderopt {
+ struct {
+ int header_count;
+ int current_level;
+ } toc_data;
+
+ unsigned int flags;
+
+ /* extra callbacks */
+ void (*link_attributes)(struct buf *ob, struct buf *url, void *self);
+};
+
typedef enum {
HTML_SKIP_HTML = (1 << 0),
HTML_SKIP_STYLE = (1 << 1),
@@ -32,7 +44,7 @@ typedef enum {
HTML_HARD_WRAP = (1 << 9),
HTML_GITHUB_BLOCKCODE = (1 << 10),
HTML_USE_XHTML = (1 << 11),
-} render_mode;
+} html_render_mode;
typedef enum {
HTML_TAG_NONE = 0,
@@ -47,13 +59,10 @@ int
sdhtml_tag(const char *tag_data, size_t tag_size, const char *tagname);
extern void
-sdhtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags, void *extra);
-
-extern void
-sdhtml_toc_renderer(struct mkd_renderer *renderer, void *extra);
+sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options_ptr, unsigned int render_flags);
extern void
-sdhtml_free_renderer(struct mkd_renderer *renderer);
+sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options_ptr);
extern void
sdhtml_smartypants(struct buf *ob, struct buf *text);
View
26 src/html_smartypants.c
@@ -36,6 +36,7 @@ static size_t smartypants_cb__dash(struct buf *ob, struct smartypants_data *smrt
static size_t smartypants_cb__parens(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size);
static size_t smartypants_cb__squote(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size);
static size_t smartypants_cb__backtick(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size);
+static size_t smartypants_cb__escape(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size);
static size_t (*smartypants_cb_ptrs[])
(struct buf *, struct smartypants_data *, char, const char *, size_t) =
@@ -50,6 +51,7 @@ static size_t (*smartypants_cb_ptrs[])
smartypants_cb__number, /* 7 */
smartypants_cb__ltag, /* 8 */
smartypants_cb__backtick, /* 9 */
+ smartypants_cb__escape, /* 10 */
};
static const char smartypants_cb_chars[] = {
@@ -58,7 +60,7 @@ static const char smartypants_cb_chars[] = {
0, 0, 4, 0, 0, 0, 5, 3, 2, 0, 0, 0, 0, 1, 6, 0,
0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0,
9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -297,6 +299,28 @@ smartypants_cb__ltag(struct buf *ob, struct smartypants_data *smrt, char previou
return i;
}
+static size_t
+smartypants_cb__escape(struct buf *ob, struct smartypants_data *smrt, char previous_char, const char *text, size_t size)
+{
+ if (size < 2)
+ return 0;
+
+ switch (text[1]) {
+ case '\\':
+ case '"':
+ case '\'':
+ case '.':
+ case '-':
+ case '`':
+ bufputc(ob, text[1]);
+ return 1;
+
+ default:
+ bufputc(ob, '\\');
+ return 0;
+ }
+}
+
#if 0
static struct {
char c0;
View
241 src/markdown.c
@@ -60,6 +60,7 @@ static size_t char_autolink_url(struct buf *ob, struct render *rndr, char *data,
static size_t char_autolink_email(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t size);
static size_t char_autolink_www(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t size);
static size_t char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t size);
+static size_t char_superscript(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t size);
enum markdown_char_t {
MD_CHAR_NONE = 0,
@@ -72,7 +73,8 @@ enum markdown_char_t {
MD_CHAR_ENTITITY,
MD_CHAR_AUTOLINK_URL,
MD_CHAR_AUTOLINK_EMAIL,
- MD_CHAR_AUTOLINK_WWW
+ MD_CHAR_AUTOLINK_WWW,
+ MD_CHAR_SUPERSCRIPT,
};
static char_trigger markdown_char_ptrs[] = {
@@ -87,11 +89,14 @@ static char_trigger markdown_char_ptrs[] = {
&char_autolink_url,
&char_autolink_email,
&char_autolink_www,
+ &char_superscript,
};
/* render • structure containing one particular render */
struct render {
- struct mkd_renderer make;
+ struct sd_callbacks cb;
+ void *opaque;
+
struct array refs;
char active_char[256];
struct parray work_bufs[2];
@@ -351,10 +356,10 @@ parse_inline(struct buf *ob, struct render *rndr, char *data, size_t size)
end++;
}
- if (rndr->make.normal_text) {
+ if (rndr->cb.normal_text) {
work.data = data + i;
work.size = end - i;
- rndr->make.normal_text(ob, &work, rndr->make.opaque);
+ rndr->cb.normal_text(ob, &work, rndr->opaque);
}
else
bufput(ob, data + i, end - i);
@@ -394,20 +399,28 @@ find_emph_char(char *data, size_t size, char c)
i++; continue;
}
- /* skipping a code span */
if (data[i] == '`') {
+ size_t span_nb = 0, bt;
size_t tmp_i = 0;
- i++;
- while (i < size && data[i] != '`') {
- if (!tmp_i && data[i] == c) tmp_i = i;
- i++;
+ /* counting the number of opening backticks */
+ while (i < size && data[i] == '`') {
+ i++; span_nb++;
}
- if (i >= size)
- return tmp_i;
+ if (i >= size) return 0;
+
+ /* finding the matching closing sequence */
+ bt = 0;
+ while (i < size && bt < span_nb) {
+ if (!tmp_i && data[i] == c) tmp_i = i;
+ if (data[i] == '`') bt++;
+ else bt = 0;
+ i++;
+ }
- i++;
+ if (i >= size) return tmp_i;
+ i++;
}
/* skipping a link */
else if (data[i] == '[') {
@@ -458,7 +471,7 @@ parse_emph1(struct buf *ob, struct render *rndr, char *data, size_t size, char c
struct buf *work = 0;
int r;
- if (!rndr->make.emphasis) return 0;
+ if (!rndr->cb.emphasis) return 0;
/* skipping one symbol if coming from emph3 */
if (size > 1 && data[0] == c && data[1] == c) i = 1;
@@ -483,7 +496,7 @@ parse_emph1(struct buf *ob, struct render *rndr, char *data, size_t size, char c
work = rndr_newbuf(rndr, BUFFER_SPAN);
parse_inline(work, rndr, data, i);
- r = rndr->make.emphasis(ob, work, rndr->make.opaque);
+ r = rndr->cb.emphasis(ob, work, rndr->opaque);
rndr_popbuf(rndr, BUFFER_SPAN);
return r ? i + 1 : 0;
}
@@ -501,7 +514,7 @@ parse_emph2(struct buf *ob, struct render *rndr, char *data, size_t size, char c
struct buf *work = 0;
int r;
- render_method = (c == '~') ? rndr->make.strikethrough : rndr->make.double_emphasis;
+ render_method = (c == '~') ? rndr->cb.strikethrough : rndr->cb.double_emphasis;
if (!render_method)
return 0;
@@ -514,7 +527,7 @@ parse_emph2(struct buf *ob, struct render *rndr, char *data, size_t size, char c
if (i + 1 < size && data[i] == c && data[i + 1] == c && i && !isspace(data[i - 1])) {
work = rndr_newbuf(rndr, BUFFER_SPAN);
parse_inline(work, rndr, data, i);
- r = render_method(ob, work, rndr->make.opaque);
+ r = render_method(ob, work, rndr->opaque);
rndr_popbuf(rndr, BUFFER_SPAN);
return r ? i + 2 : 0;
}
@@ -540,12 +553,12 @@ parse_emph3(struct buf *ob, struct render *rndr, char *data, size_t size, char c
if (data[i] != c || isspace(data[i - 1]))
continue;
- if (i + 2 < size && data[i + 1] == c && data[i + 2] == c && rndr->make.triple_emphasis) {
+ if (i + 2 < size && data[i + 1] == c && data[i + 2] == c && rndr->cb.triple_emphasis) {
/* triple symbol found */
struct buf *work = rndr_newbuf(rndr, BUFFER_SPAN);
parse_inline(work, rndr, data, i);
- r = rndr->make.triple_emphasis(ob, work, rndr->make.opaque);
+ r = rndr->cb.triple_emphasis(ob, work, rndr->opaque);
rndr_popbuf(rndr, BUFFER_SPAN);
return r ? i + 3 : 0;
@@ -610,7 +623,7 @@ char_linebreak(struct buf *ob, struct render *rndr, char *data, size_t offset, s
while (ob->size && ob->data[ob->size - 1] == ' ')
ob->size--;
- return rndr->make.linebreak(ob, rndr->make.opaque) ? 1 : 0;
+ return rndr->cb.linebreak(ob, rndr->opaque) ? 1 : 0;
}
@@ -646,10 +659,10 @@ char_codespan(struct buf *ob, struct render *rndr, char *data, size_t offset, si
/* real code span */
if (f_begin < f_end) {
struct buf work = { data + f_begin, f_end - f_begin, 0, 0, 0 };
- if (!rndr->make.codespan(ob, &work, rndr->make.opaque))
+ if (!rndr->cb.codespan(ob, &work, rndr->opaque))
end = 0;
} else {
- if (!rndr->make.codespan(ob, 0, rndr->make.opaque))
+ if (!rndr->cb.codespan(ob, 0, rndr->opaque))
end = 0;
}
@@ -668,10 +681,10 @@ char_escape(struct buf *ob, struct render *rndr, char *data, size_t offset, size
if (strchr(escape_chars, data[1]) == NULL)
return 0;
- if (rndr->make.normal_text) {
+ if (rndr->cb.normal_text) {
work.data = data + 1;
work.size = 1;
- rndr->make.normal_text(ob, &work, rndr->make.opaque);
+ rndr->cb.normal_text(ob, &work, rndr->opaque);
}
else bufputc(ob, data[1]);
}
@@ -698,10 +711,10 @@ char_entity(struct buf *ob, struct render *rndr, char *data, size_t offset, size
else
return 0; /* lone '&' */
- if (rndr->make.entity) {
+ if (rndr->cb.entity) {
work.data = data;
work.size = end;
- rndr->make.entity(ob, &work, rndr->make.opaque);
+ rndr->cb.entity(ob, &work, rndr->opaque);
}
else bufput(ob, data, end);
@@ -718,16 +731,16 @@ char_langle_tag(struct buf *ob, struct render *rndr, char *data, size_t offset,
int ret = 0;
if (end > 2) {
- if (rndr->make.autolink && altype != MKDA_NOT_AUTOLINK) {
+ if (rndr->cb.autolink && altype != MKDA_NOT_AUTOLINK) {
struct buf *u_link = rndr_newbuf(rndr, BUFFER_SPAN);
work.data = data + 1;
work.size = end - 2;
unscape_text(u_link, &work);
- ret = rndr->make.autolink(ob, u_link, altype, rndr->make.opaque);
+ ret = rndr->cb.autolink(ob, u_link, altype, rndr->opaque);
rndr_popbuf(rndr, BUFFER_SPAN);
}
- else if (rndr->make.raw_html_tag)
- ret = rndr->make.raw_html_tag(ob, &work, rndr->make.opaque);
+ else if (rndr->cb.raw_html_tag)
+ ret = rndr->cb.raw_html_tag(ob, &work, rndr->opaque);
}
if (!ret) return 0;
@@ -740,7 +753,7 @@ char_autolink_www(struct buf *ob, struct render *rndr, char *data, size_t offset
struct buf *link, *link_url;
size_t link_len, rewind;
- if (!rndr->make.link)
+ if (!rndr->cb.link)
return 0;
link = rndr_newbuf(rndr, BUFFER_SPAN);
@@ -751,7 +764,7 @@ char_autolink_www(struct buf *ob, struct render *rndr, char *data, size_t offset
bufput(link_url, link->data, link->size);
ob->size -= rewind;
- rndr->make.link(ob, link_url, NULL, link, rndr->make.opaque);
+ rndr->cb.link(ob, link_url, NULL, link, rndr->opaque);
rndr_popbuf(rndr, BUFFER_SPAN);
}
@@ -765,14 +778,14 @@ char_autolink_email(struct buf *ob, struct render *rndr, char *data, size_t offs
struct buf *link;
size_t link_len, rewind;
- if (!rndr->make.autolink)
+ if (!rndr->cb.autolink)
return 0;
link = rndr_newbuf(rndr, BUFFER_SPAN);
if ((link_len = sd_autolink__email(&rewind, link, data, offset, size)) > 0) {
ob->size -= rewind;
- rndr->make.autolink(ob, link, MKDA_EMAIL, rndr->make.opaque);
+ rndr->cb.autolink(ob, link, MKDA_EMAIL, rndr->opaque);
}
rndr_popbuf(rndr, BUFFER_SPAN);
@@ -785,14 +798,14 @@ char_autolink_url(struct buf *ob, struct render *rndr, char *data, size_t offset
struct buf *link;
size_t link_len, rewind;
- if (!rndr->make.autolink)
+ if (!rndr->cb.autolink)
return 0;
link = rndr_newbuf(rndr, BUFFER_SPAN);
if ((link_len = sd_autolink__url(&rewind, link, data, offset, size)) > 0) {
ob->size -= rewind;
- rndr->make.autolink(ob, link, MKDA_NORMAL, rndr->make.opaque);
+ rndr->cb.autolink(ob, link, MKDA_NORMAL, rndr->opaque);
}
rndr_popbuf(rndr, BUFFER_SPAN);
@@ -813,7 +826,7 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
int text_has_nl = 0, ret = 0;
/* checking whether the correct renderer exists */
- if ((is_img && !rndr->make.image) || (!is_img && !rndr->make.link))
+ if ((is_img && !rndr->cb.image) || (!is_img && !rndr->cb.link))
goto cleanup;
/* looking for the matching closing bracket */
@@ -1010,9 +1023,9 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
if (ob->size && ob->data[ob->size - 1] == '!')
ob->size -= 1;
- ret = rndr->make.image(ob, u_link, title, content, rndr->make.opaque);
+ ret = rndr->cb.image(ob, u_link, title, content, rndr->opaque);
} else {
- ret = rndr->make.link(ob, u_link, title, content, rndr->make.opaque);
+ ret = rndr->cb.link(ob, u_link, title, content, rndr->opaque);
}
/* cleanup */
@@ -1021,7 +1034,43 @@ char_link(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t
return ret ? i : 0;
}
+static size_t
+char_superscript(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t size)
+{
+ size_t sup_start, sup_len;
+ struct buf *sup;
+ if (!rndr->cb.superscript)
+ return 0;
+
+ if (size < 2)
+ return 0;
+
+ if (data[1] == '(') {
+ sup_start = sup_len = 2;
+
+ while (sup_len < size && data[sup_len] != ')' && data[sup_len - 1] != '\\')
+ sup_len++;
+
+ if (sup_len == size)
+ return 0;
+ } else {
+ sup_start = sup_len = 1;
+
+ while (sup_len < size && !isspace(data[sup_len]))
+ sup_len++;
+ }
+
+ if (sup_len - sup_start == 0)
+ return (sup_start == 2) ? 3 : 0;
+
+ sup = rndr_newbuf(rndr, BUFFER_SPAN);
+ parse_inline(sup, rndr, data + sup_start, sup_len - sup_start);
+ rndr->cb.superscript(ob, sup, rndr->opaque);
+ rndr_popbuf(rndr, BUFFER_SPAN);
+
+ return (sup_start == 2) ? sup_len + 1 : sup_len;
+}
/*********************************
* BLOCK-LEVEL PARSING FUNCTIONS *
@@ -1278,8 +1327,8 @@ parse_blockquote(struct buf *ob, struct render *rndr, char *data, size_t size)
}
parse_block(out, rndr, work_data, work_size);
- if (rndr->make.blockquote)
- rndr->make.blockquote(ob, out, rndr->make.opaque);
+ if (rndr->cb.blockquote)
+ rndr->cb.blockquote(ob, out, rndr->opaque);
rndr_popbuf(rndr, BUFFER_BLOCK);
return end;
}
@@ -1302,7 +1351,7 @@ parse_paragraph(struct buf *ob, struct render *rndr, char *data, size_t size)
break;
if (rndr->ext_flags & MKDEXT_LAX_HTML_BLOCKS) {
- if (data[i] == '<' && rndr->make.blockhtml && parse_htmlblock(ob, rndr, data + i, size - i, 0)) {
+ if (data[i] == '<' && rndr->cb.blockhtml && parse_htmlblock(ob, rndr, data + i, size - i, 0)) {
end = i;
break;
}
@@ -1323,8 +1372,8 @@ parse_paragraph(struct buf *ob, struct render *rndr, char *data, size_t size)
if (!level) {
struct buf *tmp = rndr_newbuf(rndr, BUFFER_BLOCK);
parse_inline(tmp, rndr, work.data, work.size);
- if (rndr->make.paragraph)
- rndr->make.paragraph(ob, tmp, rndr->make.opaque);
+ if (rndr->cb.paragraph)
+ rndr->cb.paragraph(ob, tmp, rndr->opaque);
rndr_popbuf(rndr, BUFFER_BLOCK);
} else {
struct buf *header_work;
@@ -1345,8 +1394,8 @@ parse_paragraph(struct buf *ob, struct render *rndr, char *data, size_t size)
struct buf *tmp = rndr_newbuf(rndr, BUFFER_BLOCK);
parse_inline(tmp, rndr, work.data, work.size);
- if (rndr->make.paragraph)
- rndr->make.paragraph(ob, tmp, rndr->make.opaque);
+ if (rndr->cb.paragraph)
+ rndr->cb.paragraph(ob, tmp, rndr->opaque);
rndr_popbuf(rndr, BUFFER_BLOCK);
work.data += beg;
@@ -1358,8 +1407,8 @@ parse_paragraph(struct buf *ob, struct render *rndr, char *data, size_t size)
header_work = rndr_newbuf(rndr, BUFFER_SPAN);
parse_inline(header_work, rndr, work.data, work.size);
- if (rndr->make.header)
- rndr->make.header(ob, header_work, (int)level, rndr->make.opaque);
+ if (rndr->cb.header)
+ rndr->cb.header(ob, header_work, (int)level, rndr->opaque);
rndr_popbuf(rndr, BUFFER_SPAN);
}
@@ -1404,8 +1453,8 @@ parse_fencedcode(struct buf *ob, struct render *rndr, char *data, size_t size)
if (work->size && work->data[work->size - 1] != '\n')
bufputc(work, '\n');
- if (rndr->make.blockcode)
- rndr->make.blockcode(ob, work, lang.size ? &lang : NULL, rndr->make.opaque);
+ if (rndr->cb.blockcode)
+ rndr->cb.blockcode(ob, work, lang.size ? &lang : NULL, rndr->opaque);
rndr_popbuf(rndr, BUFFER_BLOCK);
return beg;
@@ -1445,8 +1494,8 @@ parse_blockcode(struct buf *ob, struct render *rndr, char *data, size_t size)
bufputc(work, '\n');
- if (rndr->make.blockcode)
- rndr->make.blockcode(ob, work, NULL, rndr->make.opaque);
+ if (rndr->cb.blockcode)
+ rndr->cb.blockcode(ob, work, NULL, rndr->opaque);
rndr_popbuf(rndr, BUFFER_BLOCK);
return beg;
@@ -1560,8 +1609,8 @@ parse_listitem(struct buf *ob, struct render *rndr, char *data, size_t size, int
}
/* render of li itself */
- if (rndr->make.listitem)
- rndr->make.listitem(ob, inter, *flags, rndr->make.opaque);
+ if (rndr->cb.listitem)
+ rndr->cb.listitem(ob, inter, *flags, rndr->opaque);
rndr_popbuf(rndr, BUFFER_SPAN);
rndr_popbuf(rndr, BUFFER_SPAN);
@@ -1586,8 +1635,8 @@ parse_list(struct buf *ob, struct render *rndr, char *data, size_t size, int fla
break;
}
- if (rndr->make.list)
- rndr->make.list(ob, work, flags, rndr->make.opaque);
+ if (rndr->cb.list)
+ rndr->cb.list(ob, work, flags, rndr->opaque);
rndr_popbuf(rndr, BUFFER_BLOCK);
return i;
}
@@ -1618,8 +1667,8 @@ parse_atxheader(struct buf *ob, struct render *rndr, char *data, size_t size)
parse_inline(work, rndr, data + i, end - i);
- if (rndr->make.header)
- rndr->make.header(ob, work, (int)level, rndr->make.opaque);
+ if (rndr->cb.header)
+ rndr->cb.header(ob, work, (int)level, rndr->opaque);
rndr_popbuf(rndr, BUFFER_SPAN);
}
@@ -1693,8 +1742,8 @@ parse_htmlblock(struct buf *ob, struct render *rndr, char *data, size_t size, in
if (j) {
work.size = i + j;
- if (do_render && rndr->make.blockhtml)
- rndr->make.blockhtml(ob, &work, rndr->make.opaque);
+ if (do_render && rndr->cb.blockhtml)
+ rndr->cb.blockhtml(ob, &work, rndr->opaque);
return work.size;
}
}
@@ -1710,8 +1759,8 @@ parse_htmlblock(struct buf *ob, struct render *rndr, char *data, size_t size, in
j = is_empty(data + i, size - i);
if (j) {
work.size = i + j;
- if (do_render && rndr->make.blockhtml)
- rndr->make.blockhtml(ob, &work, rndr->make.opaque);
+ if (do_render && rndr->cb.blockhtml)
+ rndr->cb.blockhtml(ob, &work, rndr->opaque);
return work.size;
}
}
@@ -1752,8 +1801,8 @@ parse_htmlblock(struct buf *ob, struct render *rndr, char *data, size_t size, in
/* the end of the block has been found */
work.size = i;
- if (do_render && rndr->make.blockhtml)
- rndr->make.blockhtml(ob, &work, rndr->make.opaque);
+ if (do_render && rndr->cb.blockhtml)
+ rndr->cb.blockhtml(ob, &work, rndr->opaque);
return i;
}
@@ -1764,6 +1813,9 @@ parse_table_row(struct buf *ob, struct render *rndr, char *data, size_t size, si
size_t i = 0, col;
struct buf *row_work = 0;
+ if (!rndr->cb.table_cell || !rndr->cb.table_row)
+ return;
+
row_work = rndr_newbuf(rndr, BUFFER_SPAN);
if (i < size && data[i] == '|')
@@ -1789,8 +1841,7 @@ parse_table_row(struct buf *ob, struct render *rndr, char *data, size_t size, si
cell_end--;
parse_inline(cell_work, rndr, data + cell_start, 1 + cell_end - cell_start);
- if (rndr->make.table_cell)
- rndr->make.table_cell(row_work, cell_work, col_data ? col_data[col] : 0, rndr->make.opaque);
+ rndr->cb.table_cell(row_work, cell_work, col_data[col], rndr->opaque);
rndr_popbuf(rndr, BUFFER_SPAN);
i++;
@@ -1798,12 +1849,10 @@ parse_table_row(struct buf *ob, struct render *rndr, char *data, size_t size, si
for (; col < columns; ++col) {
struct buf empty_cell = {0, 0, 0, 0, 0};
- if (rndr->make.table_cell)
- rndr->make.table_cell(row_work, &empty_cell, col_data ? col_data[col] : 0, rndr->make.opaque);
+ rndr->cb.table_cell(row_work, &empty_cell, col_data[col], rndr->opaque);
}
- if (rndr->make.table_row)
- rndr->make.table_row(ob, row_work, rndr->make.opaque);
+ rndr->cb.table_row(ob, row_work, rndr->opaque);
rndr_popbuf(rndr, BUFFER_SPAN);
}
@@ -1845,6 +1894,8 @@ parse_table_header(struct buf *ob, struct render *rndr, char *data, size_t size,
for (col = 0; col < *columns && i < under_end; ++col) {
size_t dashes = 0;
+ (*column_data)[col] |= MKD_TABLE_HEADER;
+
while (i < under_end && (data[i] == ' ' || data[i] == '\t'))
i++;
@@ -1917,8 +1968,8 @@ parse_table(struct buf *ob, struct render *rndr, char *data, size_t size)
i++;
}
- if (rndr->make.table)
- rndr->make.table(ob, header_work, body_work, rndr->make.opaque);
+ if (rndr->cb.table)
+ rndr->cb.table(ob, header_work, body_work, rndr->opaque);
}
free(col_data);
@@ -1946,7 +1997,7 @@ parse_block(struct buf *ob, struct render *rndr, char *data, size_t size)
if (is_atxheader(rndr, txt_data, end))
beg += parse_atxheader(ob, rndr, txt_data, end);
- else if (data[beg] == '<' && rndr->make.blockhtml &&
+ else if (data[beg] == '<' && rndr->cb.blockhtml &&
(i = parse_htmlblock(ob, rndr, txt_data, end, 1)) != 0)
beg += i;
@@ -1954,8 +2005,8 @@ parse_block(struct buf *ob, struct render *rndr, char *data, size_t size)
beg += i;
else if (is_hrule(txt_data, end)) {
- if (rndr->make.hrule)
- rndr->make.hrule(ob, rndr->make.opaque);
+ if (rndr->cb.hrule)
+ rndr->cb.hrule(ob, rndr->opaque);
while (beg < size && data[beg] != '\n')
beg++;
@@ -2128,14 +2179,21 @@ static void expand_tabs(struct buf *ob, const char *line, size_t size)
/* markdown • parses the input buffer and renders it into the output buffer */
void
-sd_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer, unsigned int extensions) {
+sd_markdown(struct buf *ob,
+ const struct buf *ib,
+ unsigned int extensions,
+ const struct sd_callbacks *callbacks,
+ void *opaque) {
+
+ static const float MARKDOWN_GROW_FACTOR = 1.4f;
+
struct link_ref *lr;
struct buf *text;
size_t i, beg, end;
struct render rndr;
/* filling the render structure */
- if (!rndrer)
+ if (!callbacks)
return;
text = bufnew(64);
@@ -2145,28 +2203,30 @@ sd_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer, u
/* Preallocate enough space for our buffer to avoid expanding while copying */
bufgrow(text, ib->size);
- memcpy(&rndr.make, rndrer, sizeof(struct mkd_renderer));
+ memcpy(&rndr.cb, callbacks, sizeof(struct sd_callbacks));
arr_init(&rndr.refs, sizeof (struct link_ref));
parr_init(&rndr.work_bufs[BUFFER_BLOCK]);
parr_init(&rndr.work_bufs[BUFFER_SPAN]);
- for (i = 0; i < 256; i++)
- rndr.active_char[i] = 0;
+/* for (i = 0; i < 256; i++)
+ rndr.active_char[i] = 0; */
+
+ memset(rndr.active_char, 0x0, 256);
- if (rndr.make.emphasis || rndr.make.double_emphasis || rndr.make.triple_emphasis) {
+ if (rndr.cb.emphasis || rndr.cb.double_emphasis || rndr.cb.triple_emphasis) {
rndr.active_char['*'] = MD_CHAR_EMPHASIS;
rndr.active_char['_'] = MD_CHAR_EMPHASIS;
if (extensions & MKDEXT_STRIKETHROUGH)
rndr.active_char['~'] = MD_CHAR_EMPHASIS;
}
- if (rndr.make.codespan)
+ if (rndr.cb.codespan)
rndr.active_char['`'] = MD_CHAR_CODESPAN;
- if (rndr.make.linebreak)
+ if (rndr.cb.linebreak)
rndr.active_char['\n'] = MD_CHAR_LINEBREAK;
- if (rndr.make.image || rndr.make.link)
+ if (rndr.cb.image || rndr.cb.link)
rndr.active_char['['] = MD_CHAR_LINK;
rndr.active_char['<'] = MD_CHAR_LANGLE;
@@ -2179,8 +2239,12 @@ sd_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer, u
rndr.active_char['w'] = MD_CHAR_AUTOLINK_WWW;
}
+ if (extensions & MKDEXT_SUPERSCRIPT)
+ rndr.active_char['^'] = MD_CHAR_SUPERSCRIPT;
+
/* Extension data */
rndr.ext_flags = extensions;
+ rndr.opaque = opaque;
rndr.max_nesting = 16;
/* first pass: looking for references, copying everything else */
@@ -2211,9 +2275,12 @@ sd_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer, u
if (rndr.refs.size)
qsort(rndr.refs.base, rndr.refs.size, rndr.refs.unit, cmp_link_ref_sort);
+ /* pre-grow the output buffer to minimize allocations */
+ bufgrow(ob, text->size * MARKDOWN_GROW_FACTOR);
+
/* second pass: actual rendering */
- if (rndr.make.doc_header)
- rndr.make.doc_header(ob, rndr.make.opaque);
+ if (rndr.cb.doc_header)
+ rndr.cb.doc_header(ob, rndr.opaque);
if (text->size) {
/* adding a final newline if not already present */
@@ -2223,8 +2290,8 @@ sd_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer, u
parse_block(ob, &rndr, text->data, text->size);
}
- if (rndr.make.doc_footer)
- rndr.make.doc_footer(ob, rndr.make.opaque);
+ if (rndr.cb.doc_footer)
+ rndr.cb.doc_footer(ob, rndr.opaque);
/* clean-up */
bufrelease(text);
View
25 src/markdown.h
@@ -31,13 +31,21 @@
* TYPE DEFINITIONS *
********************/
-/* mkd_autolink type of autolink */
+/* mkd_autolink - type of autolink */
enum mkd_autolink {
MKDA_NOT_AUTOLINK, /* used internally when it is not an autolink*/
MKDA_NORMAL, /* normal http/http/ftp/mailto/etc link */
MKDA_EMAIL, /* e-mail link without explit mailto: */
};
+enum mkd_tableflags {
+ MKD_TABLE_ALIGN_L = 1,
+ MKD_TABLE_ALIGN_R = 2,
+ MKD_TABLE_ALIGN_CENTER = 3,
+ MKD_TABLE_ALIGNMASK = 3,
+ MKD_TABLE_HEADER = 4
+};
+
enum mkd_extensions {
MKDEXT_NO_INTRA_EMPHASIS = (1 << 0),
MKDEXT_TABLES = (1 << 1),
@@ -46,10 +54,11 @@ enum mkd_extensions {
MKDEXT_STRIKETHROUGH = (1 << 4),
MKDEXT_LAX_HTML_BLOCKS = (1 << 5),
MKDEXT_SPACE_HEADERS = (1 << 6),
+ MKDEXT_SUPERSCRIPT = (1 << 7),
};
-/* mkd_renderer • functions for rendering parsed data */
-struct mkd_renderer {
+/* sd_callbacks - functions for rendering parsed data */
+struct sd_callbacks {
/* block level callbacks - NULL skips the block */
void (*blockcode)(struct buf *ob, struct buf *text, struct buf *lang, void *opaque);
void (*blockquote)(struct buf *ob, struct buf *text, void *opaque);
@@ -75,6 +84,7 @@ struct mkd_renderer {
int (*raw_html_tag)(struct buf *ob, struct buf *tag, void *opaque);
int (*triple_emphasis)(struct buf *ob, struct buf *text, void *opaque);
int (*strikethrough)(struct buf *ob, struct buf *text, void *opaque);
+ int (*superscript)(struct buf *ob, struct buf *text, void *opaque);
/* low level callbacks - NULL copies input directly into the output */
void (*entity)(struct buf *ob, struct buf *entity, void *opaque);
@@ -83,9 +93,6 @@ struct mkd_renderer {
/* header and footer */
void (*doc_header)(struct buf *ob, void *opaque);
void (*doc_footer)(struct buf *ob, void *opaque);
-
- /* user data */
- void *opaque;
};
/*********
@@ -96,17 +103,13 @@ struct mkd_renderer {
#define MKD_LIST_ORDERED 1
#define MKD_LI_BLOCK 2 /* <li> containing block data */
-#define MKD_TABLE_ALIGN_L (1 << 0)
-#define MKD_TABLE_ALIGN_R (1 << 1)
-#define MKD_TABLE_ALIGN_CENTER (MKD_TABLE_ALIGN_L | MKD_TABLE_ALIGN_R)
-
/**********************
* EXPORTED FUNCTIONS *
**********************/
/* sd_markdown * parses the input buffer and renders it into the output buffer */
extern void
-sd_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndr, unsigned int extensions);
+sd_markdown(struct buf *ob, const struct buf *ib, unsigned int extensions, const struct sd_callbacks *rndr, void *opaque);
/* sd_version * returns the library version as major.minor.rev */
extern void
View
272 src/php_sundown.c
@@ -39,6 +39,254 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_sundown__construct, 0, 0, 2)
ZEND_ARG_ARRAY_INFO(0, extensions, 0)
ZEND_END_ARG_INFO()
+struct php_sundown_renderopt {
+ struct html_renderopt html;
+ zval *self;
+};
+
+static inline zval* buf2str(struct buf *text)
+{
+ zval *str;
+ MAKE_STD_ZVAL(str);
+ if (!text || !text->size) return NULL;
+ ZVAL_STRINGL(str, text->data, text->size,1);
+ return str;
+}
+
+#define SPAN_CALLBACK(method_name, ...) {\
+}
+
+//__VA_ARGS__
+
+#define BLOCK_CALLBACK(method_name, ...) {\
+}
+
+static void rndr_blockcode(struct buf *ob, struct buf *text, struct buf *lang, void *opaque)
+{
+ BLOCK_CALLBACK("block_code", 2, buf2str(text), buf2str(lang));
+}
+
+static void rndr_blockquote(struct buf *ob, struct buf *text, void *opaque)
+{
+ BLOCK_CALLBACK("block_quote", 1, buf2str(text));
+}
+
+static void rndr_raw_block(struct buf *ob, struct buf *text, void *opaque)
+{
+ BLOCK_CALLBACK("block_html", 1, buf2str(text));
+}
+
+static void rndr_header(struct buf *ob, struct buf *text, int level, void *opaque)
+{
+ BLOCK_CALLBACK("header", 2, buf2str(text), level);
+}
+
+static void rndr_hrule(struct buf *ob, void *opaque)
+{
+ BLOCK_CALLBACK("hrule", 0);
+}
+
+static void rndr_list(struct buf *ob, struct buf *text, int flags, void *opaque)
+{
+ BLOCK_CALLBACK("list", 2, buf2str(text),
+ (flags & MKD_LIST_ORDERED) ? CSTR2SYM("ordered") : CSTR2SYM("unordered"));
+}
+
+static void rndr_listitem(struct buf *ob, struct buf *text, int flags, void *opaque)
+{
+ BLOCK_CALLBACK("list_item", 2, buf2str(text),
+ (flags & MKD_LIST_ORDERED) ? CSTR2SYM("ordered") : CSTR2SYM("unordered"));
+}
+
+static void rndr_paragraph(struct buf *ob, struct buf *text, void *opaque)
+{
+ BLOCK_CALLBACK("paragraph", 1, buf2str(text));
+}
+
+static void rndr_table(struct buf *ob, struct buf *header, struct buf *body, void *opaque)
+{
+ BLOCK_CALLBACK("table", 2, buf2str(header), buf2str(body));
+}
+
+static void rndr_tablerow(struct buf *ob, struct buf *text, void *opaque)
+{
+ BLOCK_CALLBACK("table_row", 1, buf2str(text));
+}
+
+static void rndr_tablecell(struct buf *ob, struct buf *text, int align, void *opaque)
+{
+ zval php_align;
+
+ switch (align) {
+ case MKD_TABLE_ALIGN_L:
+ ZVAL_STRING(&php_align, "left", 1);
+ break;
+
+ case MKD_TABLE_ALIGN_R:
+ ZVAL_STRING(&php_align, "right", 1);
+ break;
+
+ case MKD_TABLE_ALIGN_CENTER:
+ ZVAL_STRING(&php_align, "center", 1);
+ break;
+
+ default:
+ ZVAL_NULL(&php_align);
+ break;
+ }
+
+ BLOCK_CALLBACK("table_cell", 2, buf2str(text), php_align);
+}
+
+/***
+* SPAN LEVEL
+*/
+static int rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, void *opaque)
+{
+ SPAN_CALLBACK("autolink", 2, buf2str(link),
+ type == MKDA_NORMAL ? "url" : "email");
+}
+
+static int rndr_codespan(struct buf *ob, struct buf *text, void *opaque)
+{
+ SPAN_CALLBACK("codespan", 1, buf2str(text));
+}
+
+static int rndr_double_emphasis(struct buf *ob, struct buf *text, void *opaque)
+{
+ SPAN_CALLBACK("double_emphasis", 1, buf2str(text));
+}
+
+static int rndr_emphasis(struct buf *ob, struct buf *text, void *opaque)
+{
+ SPAN_CALLBACK("emphasis", 1, buf2str(text));
+}
+
+static int rndr_image(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt, void *opaque)
+{
+ SPAN_CALLBACK("image", 3, buf2str(link), buf2str(title), buf2str(alt));
+}
+
+static int rndr_linebreak(struct buf *ob, void *opaque)
+{
+ SPAN_CALLBACK("linebreak", 0);
+}
+
+static int rndr_link(struct buf *ob, struct buf *link, struct buf *title, struct buf *content, void *opaque)
+{
+ SPAN_CALLBACK("link", 3, buf2str(link), buf2str(title), buf2str(content));
+}
+
+static int rndr_raw_html(struct buf *ob, struct buf *text, void *opaque)
+{
+ SPAN_CALLBACK("raw_html", 1, buf2str(text));
+}
+
+static int rndr_triple_emphasis(struct buf *ob, struct buf *text, void *opaque)
+{
+ SPAN_CALLBACK("triple_emphasis", 1, buf2str(text));
+}
+
+static int rndr_strikethrough(struct buf *ob, struct buf *text, void *opaque)
+{
+ SPAN_CALLBACK("strikethrough", 1, buf2str(text));
+}
+
+static int rndr_superscript(struct buf *ob, struct buf *text, void *opaque)
+{
+ SPAN_CALLBACK("superscript", 1, buf2str(text));
+}
+
+/**
+* direct writes
+*/
+static void rndr_entity(struct buf *ob, struct buf *text, void *opaque)
+{
+ BLOCK_CALLBACK("entity", 1, buf2str(text));
+}
+
+static void rndr_normal_text(struct buf *ob, struct buf *text, void *opaque)
+{
+ BLOCK_CALLBACK("normal_text", 1, buf2str(text));
+}
+
+static void rndr_doc_header(struct buf *ob, void *opaque)
+{
+ BLOCK_CALLBACK("doc_header", 0);
+}
+
+static void rndr_doc_footer(struct buf *ob, void *opaque)
+{
+ BLOCK_CALLBACK("doc_footer", 0);
+}
+
+
+static struct sd_callbacks php_sundown_callbacks = {
+ 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,
+ rndr_image,
+ rndr_linebreak,
+ rndr_link,
+ rndr_raw_html,
+ rndr_triple_emphasis,
+ rndr_strikethrough,
+ rndr_superscript,
+
+ rndr_entity,
+ rndr_normal_text,
+
+ rndr_doc_header,
+ rndr_doc_footer,
+};
+
+static const char *php_sundown_method_names[] = {
+ "block_code",
+ "block_quote",
+ "block_html",
+ "header",
+ "hrule",
+ "list",
+ "list_item",
+ "paragraph",
+ "table",
+ "table_row",
+ "table_cell",
+
+ "autolink",
+ "codespan",
+ "double_emphasis",
+ "emphasis",
+ "image",
+ "linebreak",
+ "link",
+ "raw_html",
+ "triple_emphasis",
+ "strikethrough",
+ "superscript",
+
+ "entity",
+ "normal_text",
+
+ "doc_header",
+ "doc_footer"
+};
+
+static const size_t php_sundown_method_count = sizeof(php_sundown_method_names)/sizeof(char *);
+
#define SUNDOWN_HAS_EXTENSION(name) (table != NULL && zend_hash_exists(table, name,strlen(name)+1) == 1)
static void php_sundown__get_flags(HashTable *table, unsigned int *enabled_extensions_p, unsigned int *render_flags_p)
@@ -126,7 +374,8 @@ static void php_sundown__get_flags(HashTable *table, unsigned int *enabled_exten
static void sundown__render(SundownRendererType render_type, INTERNAL_FUNCTION_PARAMETERS)
{
struct buf input_buf, *output_buf;
- struct mkd_renderer sundown_render;
+ struct sd_callbacks sundown_render;
+ struct html_renderopt opt;
unsigned int enabled_extensions = 0, render_flags = 0;
char *buffer;
int buffer_len = 0;
@@ -147,18 +396,27 @@ static void sundown__render(SundownRendererType render_type, INTERNAL_FUNCTION_P
}
php_sundown__get_flags(table, &enabled_extensions, &render_flags);
+ // setup render
switch (render_type) {
case SUNDOWN_RENDER_HTML:
- sdhtml_renderer(&sundown_render, render_flags,NULL);
+ sdhtml_renderer(&sundown_render, &opt, render_flags);
break;
case SUNDOWN_RENDER_TOC:
- sdhtml_toc_renderer(&sundown_render,NULL);
+ sdhtml_toc_renderer(&sundown_render,&opt);
break;
default:
RETURN_FALSE;
}
- sd_markdown(output_buf, &input_buf, &sundown_render, enabled_extensions);
+ //overrides
+ void **source = (void **)&php_sundown_callbacks;
+ void **dest = (void **)&sundown_render;
+ size_t i;
+ for (i = 0; i < php_sundown_method_count; ++i) {
+ dest[i] = source[i];
+ }
+
+ sd_markdown(output_buf, &input_buf, enabled_extensions, &sundown_render, &opt);
if (Z_BVAL_P(zend_read_property(sundown_class_entry, getThis(),"enable_pants",sizeof("enable_pants")-1, 0 TSRMLS_CC))) {
struct buf *smart_buf = bufnew(128);
@@ -170,7 +428,7 @@ static void sundown__render(SundownRendererType render_type, INTERNAL_FUNCTION_P
}
bufrelease(output_buf);
- sdhtml_free_renderer(&sundown_render);
+ bufrelease(&input_buf);
}
/* {{{ proto string __construct(string $string [, array $extensions])
@@ -191,7 +449,7 @@ PHP_METHOD(sundown, __construct)
MAKE_STD_ZVAL(extensions);
array_init(extensions);
}
- add_property_zval_ex(getThis(),"extensions",sizeof("extensions"),extensions TSRMLS_CC);
+ add_property_zval_ex(getThis(),"extensions",sizeof("extensions"),extensions TSRMLS_CC);
}
/* }}} */
@@ -257,7 +515,7 @@ zend_module_entry sundown_module_entry = {
STANDARD_MODULE_HEADER,
#endif
"sundown",
- NULL, /* Functions */
+ NULL, /* Functions */
PHP_MINIT(sundown), /* MINIT */
NULL, /* MSHUTDOWN */
NULL, /* RINIT */
Please sign in to comment.
Something went wrong with that request. Please try again.