diff --git a/html/html.c b/html/html.c index 44b69a2..31cd690 100755 --- a/html/html.c +++ b/html/html.c @@ -205,6 +205,21 @@ rndr_strikethrough(struct buf *ob, const struct buf *text, void *opaque) return 1; } +static int +rndr_coloredtext(struct buf *ob, const struct buf *text, const struct buf *color, void *opaque) +{ + if (!text || !text->size || !color || !color->size || !color+text->size) + return 0; + + BUFPUTSL(ob, "data, color->size); + BUFPUTSL(ob, "\">"); + bufput(ob, text->data, text->size); + BUFPUTSL(ob, ""); + + return 1; +} + static int rndr_double_emphasis(struct buf *ob, const struct buf *text, void *opaque) { @@ -734,6 +749,7 @@ sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *optio NULL, rndr_codespan, + rndr_coloredtext, rndr_spoilerspan, rndr_double_emphasis, rndr_emphasis, @@ -777,6 +793,7 @@ sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options, rndr_autolink, rndr_codespan, + rndr_coloredtext, rndr_spoilerspan, rndr_double_emphasis, rndr_emphasis, diff --git a/src/markdown.c b/src/markdown.c index fa85a71..961dc6c 100644 --- a/src/markdown.c +++ b/src/markdown.c @@ -629,6 +629,48 @@ parse_spoilerspan(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_ return 0; } +static size_t +parse_coloredtext(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size) +{ + int (*render_method)(struct buf *ob, const struct buf *text, const struct buf *color, void *opaque); + size_t len; + size_t i = 0; + struct buf *work = 0; + struct buf *color = 0; + int r; + + render_method = rndr->cb.coloredtext; + + if (!render_method) return 0; + + while (i < size) { + colorlen = find_emph_char(data + i, size - i, ':'); + if (!colorlen) return 0; + i += colorlen + if (i < size && data[i] == ':' && data[i - 1] == ':') { + color = rndr_newbuf(rndr, BUFFER_SPAN); + parse_inline(color, rndr, data, i - 1); + } + + len = find_emph_char(data + i, size - i, '<'); + if (!len) return 0; + i += len; + + if (i < size && data[i] == '<' && data[i - 1] == ':') { + work = rndr_newbuf(rndr, BUFFER_SPAN); + parse_inline(work, rndr, data, i - 1); + r = render_method(ob, work, color, rndr->opaque); + rndr_popbuf(rndr, BUFFER_SPAN); + + if (!r) return 0; + + return i + 1; + } + i++; + } + return 0; +} + /* char_emphasis • single and double emphasis parsing */ static size_t char_emphasis(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t max_rewind, size_t max_lookbehind, size_t size) @@ -643,6 +685,13 @@ char_emphasis(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t ma return ret + 2; } + if (size > 4 && c == '>' && data[1] == 'c' && data[2] == ':') { + if(_isspace(data[2]) || (ret = parse_coloredtext(ob, rndr, data + 2, size - 2)) == 0) + return 0; + + return ret + 3; + } + if (size > 2 && data[1] != c) { /* whitespace cannot follow an opening emphasis; @@ -1480,6 +1529,25 @@ prefix_blockspoiler(uint8_t *data, size_t size) return 0; } +static size_t +prefix_coloredtext(uint8_t *data, size_t size) +{ + size_t i = 0; + if (i < size && data[i] == ' ') i++; + if (i < size && data[i] == ' ') i++; + if (i < size && data[i] == ' ') i++; + + if (i + 2 < size && data[i] == '>' && data[i + 1] == 'c' && data[i + 2] == ':') { + size_t coloredspan = find_emph_char(data + i + 2, size - i - 1, '<'); + if (i + coloredspan < size && coloredspan > 0 && data[i + coloredspan] == ':') + return 0; + + return i + 3; + } + + return 0; +} + /* prefix_code • returns prefix length for block code*/ static size_t prefix_code(uint8_t *data, size_t size) diff --git a/src/markdown.h b/src/markdown.h index c70a2bb..8cc7abd 100644 --- a/src/markdown.h +++ b/src/markdown.h @@ -82,6 +82,7 @@ struct sd_callbacks { /* span level callbacks - NULL or return 0 prints the span verbatim */ int (*autolink)(struct buf *ob, const struct buf *link, enum mkd_autolink type, void *opaque); int (*codespan)(struct buf *ob, const struct buf *text, void *opaque); + int (*coloredtext)(struct buf *ob, const struct buf *text, const struct buf *color, void *opaque); int (*spoilerspan)(struct buf *ob, const struct buf *text, void *opaque); int (*double_emphasis)(struct buf *ob, const struct buf *text, void *opaque); int (*emphasis)(struct buf *ob, const struct buf *text, void *opaque);