diff --git a/Makefile b/Makefile index baca6875..fb268c99 100644 --- a/Makefile +++ b/Makefile @@ -44,7 +44,7 @@ libsundown.so: libsundown.so.1 ln -f -s $^ $@ libsundown.so.1: $(SUNDOWN_SRC) - $(CC) $(LDFLAGS) -shared -Wl $^ -o $@ + $(CC) $(LDFLAGS) -shared $^ -o $@ # executables diff --git a/html/html.c b/html/html.c index 7f08ee8e..803eaf5d 100755 --- a/html/html.c +++ b/html/html.c @@ -27,6 +27,7 @@ #define USE_XHTML(opt) (opt->flags & HTML_USE_XHTML) + int sdhtml_is_tag(const uint8_t *tag_data, size_t tag_size, const char *tagname) { @@ -169,6 +170,18 @@ rndr_codespan(struct buf *ob, const struct buf *text, void *opaque) return 1; } +static int +rndr_ins(struct buf *ob, const struct buf *text, void *opaque) +{ + if (!text || !text->size) + return 0; + + BUFPUTSL(ob, ""); + bufput(ob, text->data, text->size); + BUFPUTSL(ob, ""); + return 1; +} + static int rndr_strikethrough(struct buf *ob, const struct buf *text, void *opaque) { @@ -214,11 +227,23 @@ rndr_linebreak(struct buf *ob, void *opaque) static void rndr_header(struct buf *ob, const struct buf *text, int level, void *opaque) -{ +{ struct html_renderopt *options = opaque; if (ob->size) bufputc(ob, '\n'); + + if (options->flags & HTML_OUTLINE) + { + if(options->outline_data.current_level >= level) + { + BUFPUTSL(ob, ""); + options->outline_data.open_section_count--; + } + bufprintf(ob, "
\n", level); + options->outline_data.open_section_count++; + options->outline_data.current_level = level; + } if (options->flags & HTML_TOC) bufprintf(ob, "", level, options->toc_data.header_count++); @@ -486,6 +511,21 @@ rndr_normal_text(struct buf *ob, const struct buf *text, void *opaque) escape_html(ob, text->data, text->size); } +static void +rndr_finalize(struct buf *ob, void *opaque) +{ + struct html_renderopt *options = opaque; + int i; + + if (options->flags & HTML_OUTLINE) { + for(i = 0; i < options->outline_data.open_section_count; i++) + { + BUFPUTSL(ob, "\n
\n"); + } + } +} + + static void toc_header(struct buf *ob, const struct buf *text, int level, void *opaque) { @@ -564,6 +604,7 @@ sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *optio toc_link, NULL, rndr_triple_emphasis, + rndr_ins, rndr_strikethrough, rndr_superscript, @@ -572,6 +613,8 @@ sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *optio NULL, toc_finalize, + + NULL, }; memset(options, 0x0, sizeof(struct html_renderopt)); @@ -605,6 +648,7 @@ sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options, rndr_link, rndr_raw_html, rndr_triple_emphasis, + rndr_ins, rndr_strikethrough, rndr_superscript, @@ -613,6 +657,8 @@ sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options, NULL, NULL, + + NULL, //rndr_finalize, }; /* Prepare the options pointer */ @@ -622,6 +668,14 @@ sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options, /* Prepare the callbacks */ memcpy(callbacks, &cb_default, sizeof(struct sd_callbacks)); + if (render_flags & HTML_OUTLINE) + { + callbacks->outline = rndr_finalize; + + options->outline_data.open_section_count = 0; + options->outline_data.current_level = 0; + } + if (render_flags & HTML_SKIP_IMAGES) callbacks->image = NULL; diff --git a/html/html.h b/html/html.h index 4c8810d4..f2556fac 100644 --- a/html/html.h +++ b/html/html.h @@ -34,6 +34,11 @@ struct html_renderopt { unsigned int flags; + struct { + int current_level; + int open_section_count; + } outline_data; + /* extra callbacks */ void (*link_attributes)(struct buf *ob, const struct buf *url, void *self); }; @@ -49,6 +54,7 @@ typedef enum { HTML_HARD_WRAP = (1 << 7), HTML_USE_XHTML = (1 << 8), HTML_ESCAPE = (1 << 9), + HTML_OUTLINE = (1 << 10), } html_render_mode; typedef enum { diff --git a/src/markdown.c b/src/markdown.c index 260483d6..207b0647 100644 --- a/src/markdown.c +++ b/src/markdown.c @@ -526,6 +526,7 @@ parse_emph2(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size int r; render_method = (c == '~') ? rndr->cb.strikethrough : rndr->cb.double_emphasis; + render_method = (c == '+') ? rndr->cb.ins : render_method; if (!render_method) return 0; @@ -598,8 +599,9 @@ char_emphasis(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t of if (size > 2 && data[1] != c) { /* whitespace cannot follow an opening emphasis; + * ins only takes two characters '++' * strikethrough only takes two characters '~~' */ - if (c == '~' || _isspace(data[1]) || (ret = parse_emph1(ob, rndr, data + 1, size - 1, c)) == 0) + if (c == '+' || c == '~' || _isspace(data[1]) || (ret = parse_emph1(ob, rndr, data + 1, size - 1, c)) == 0) return 0; return ret + 1; @@ -613,7 +615,7 @@ char_emphasis(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t of } if (size > 4 && data[1] == c && data[2] == c && data[3] != c) { - if (c == '~' || _isspace(data[3]) || (ret = parse_emph3(ob, rndr, data + 3, size - 3, c)) == 0) + if (c == '+' || c == '~' || _isspace(data[3]) || (ret = parse_emph3(ob, rndr, data + 3, size - 3, c)) == 0) return 0; return ret + 3; @@ -2415,6 +2417,8 @@ sd_markdown_new( md->active_char['_'] = MD_CHAR_EMPHASIS; if (extensions & MKDEXT_STRIKETHROUGH) md->active_char['~'] = MD_CHAR_EMPHASIS; + if (extensions & MKDEXT_INS) + md->active_char['+'] = MD_CHAR_EMPHASIS; } if (md->cb.codespan) @@ -2515,6 +2519,9 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str if (md->cb.doc_footer) md->cb.doc_footer(ob, md->opaque); + if (md->cb.outline) + md->cb.outline(ob, md->opaque); + /* clean-up */ bufrelease(text); free_link_refs(md->refs); diff --git a/src/markdown.h b/src/markdown.h index 6f6553ec..910b2fa8 100644 --- a/src/markdown.h +++ b/src/markdown.h @@ -56,6 +56,7 @@ enum mkd_extensions { MKDEXT_FENCED_CODE = (1 << 2), MKDEXT_AUTOLINK = (1 << 3), MKDEXT_STRIKETHROUGH = (1 << 4), + MKDEXT_INS = (1 << 5), MKDEXT_SPACE_HEADERS = (1 << 6), MKDEXT_SUPERSCRIPT = (1 << 7), MKDEXT_LAX_SPACING = (1 << 8), @@ -87,6 +88,7 @@ struct sd_callbacks { int (*link)(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *content, void *opaque); int (*raw_html_tag)(struct buf *ob, const struct buf *tag, void *opaque); int (*triple_emphasis)(struct buf *ob, const struct buf *text, void *opaque); + int (*ins)(struct buf *ob, const struct buf *text, void *opaque); int (*strikethrough)(struct buf *ob, const struct buf *text, void *opaque); int (*superscript)(struct buf *ob, const struct buf *text, void *opaque); @@ -97,6 +99,9 @@ struct sd_callbacks { /* header and footer */ void (*doc_header)(struct buf *ob, void *opaque); void (*doc_footer)(struct buf *ob, void *opaque); + + /* outliner */ + void (*outline)(struct buf *ob, void *opaque); }; struct sd_markdown;