diff --git a/ext/markdown.c b/ext/markdown.c index ce2b855b..a95c75b6 100755 --- a/ext/markdown.c +++ b/ext/markdown.c @@ -137,7 +137,7 @@ is_safe_link(const char *link, size_t link_len) for (i = 0; i < valid_uris_count; ++i) { size_t len = strlen(valid_uris[i]); - if (link_len > len && memcmp(link, valid_uris[i], len) == 0) + if (link_len > len && strncasecmp(link, valid_uris[i], len) == 0) return 1; } @@ -397,7 +397,7 @@ parse_emph1(struct buf *ob, struct render *rndr, char *data, size_t size, char c work = rndr_newbuf(rndr); parse_inline(work, rndr, data, i); - r = rndr->make.emphasis(ob, work, c, rndr->make.opaque); + r = rndr->make.emphasis(ob, work, rndr->make.opaque); rndr_popbuf(rndr); return r ? i + 1 : 0; } @@ -410,11 +410,14 @@ parse_emph1(struct buf *ob, struct render *rndr, char *data, size_t size, char c static size_t parse_emph2(struct buf *ob, struct render *rndr, char *data, size_t size, char c) { + int (*render_method)(struct buf *ob, struct buf *text, void *opaque); size_t i = 0, len; struct buf *work = 0; int r; - if (!rndr->make.double_emphasis) + render_method = (c == '~') ? rndr->make.strikethrough : rndr->make.double_emphasis; + + if (!render_method) return 0; while (i < size) { @@ -425,7 +428,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); parse_inline(work, rndr, data, i); - r = rndr->make.double_emphasis(ob, work, c, rndr->make.opaque); + r = render_method(ob, work, rndr->make.opaque); rndr_popbuf(rndr); return r ? i + 2 : 0; } @@ -456,7 +459,7 @@ parse_emph3(struct buf *ob, struct render *rndr, char *data, size_t size, char c struct buf *work = rndr_newbuf(rndr); parse_inline(work, rndr, data, i); - r = rndr->make.triple_emphasis(ob, work, c, rndr->make.opaque); + r = rndr->make.triple_emphasis(ob, work, rndr->make.opaque); rndr_popbuf(rndr); return r ? i + 3 : 0; @@ -484,8 +487,9 @@ char_emphasis(struct buf *ob, struct render *rndr, char *data, size_t offset, si size_t ret; if (size > 2 && data[1] != c) { - /* whitespace cannot follow an opening emphasis */ - if (isspace(data[1]) || (ret = parse_emph1(ob, rndr, data + 1, size - 1, c)) == 0) + /* whitespace cannot follow an opening emphasis; + * strikethrough only takes two characters '~~' */ + if (c == '~' || isspace(data[1]) || (ret = parse_emph1(ob, rndr, data + 1, size - 1, c)) == 0) return 0; return ret + 1; @@ -499,7 +503,7 @@ char_emphasis(struct buf *ob, struct render *rndr, char *data, size_t offset, si } if (size > 4 && data[1] == c && data[2] == c && data[3] != c) { - if (isspace(data[3]) || (ret = parse_emph3(ob, rndr, data + 3, size - 3, c)) == 0) + if (c == '~' || isspace(data[3]) || (ret = parse_emph3(ob, rndr, data + 3, size - 3, c)) == 0) return 0; return ret + 3; @@ -1970,8 +1974,13 @@ ups_markdown(struct buf *ob, struct buf *ib, const struct mkd_renderer *rndrer, if (extensions & MKDEXT_AUTOLINK) { rndr.active_char['h'] = char_autolink; // http, https + rndr.active_char['H'] = char_autolink; + rndr.active_char['f'] = char_autolink; // ftp + rndr.active_char['F'] = char_autolink; + rndr.active_char['m'] = char_autolink; // mailto + rndr.active_char['M'] = char_autolink; } /* Extension data */ diff --git a/ext/markdown.h b/ext/markdown.h index d48c8ff1..24d6f0f8 100755 --- a/ext/markdown.h +++ b/ext/markdown.h @@ -61,13 +61,14 @@ struct mkd_renderer { /* span level callbacks - NULL or return 0 prints the span verbatim */ int (*autolink)(struct buf *ob, struct buf *link, enum mkd_autolink type, void *opaque); int (*codespan)(struct buf *ob, struct buf *text, void *opaque); - int (*double_emphasis)(struct buf *ob, struct buf *text, char c, void *opaque); - int (*emphasis)(struct buf *ob, struct buf *text, char c,void *opaque); + int (*double_emphasis)(struct buf *ob, struct buf *text, void *opaque); + int (*emphasis)(struct buf *ob, struct buf *text, void *opaque); int (*image)(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt, void *opaque); int (*linebreak)(struct buf *ob, void *opaque); int (*link)(struct buf *ob, struct buf *link, struct buf *title, struct buf *content, void *opaque); int (*raw_html_tag)(struct buf *ob, struct buf *tag, void *opaque); - int (*triple_emphasis)(struct buf *ob, struct buf *text, char c, void *opaque); + int (*triple_emphasis)(struct buf *ob, struct buf *text, void *opaque); + int (*strikethrough)(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); diff --git a/ext/xhtml.c b/ext/xhtml.c index d9d9831a..5c1b507a 100755 --- a/ext/xhtml.c +++ b/ext/xhtml.c @@ -29,18 +29,23 @@ struct xhtml_renderopt { int current_level; } toc_data; + struct { + int in_squote; + int in_dquote; + } quotes; + unsigned int flags; }; -static inline int +static inline void put_scaped_char(struct buf *ob, char c) { switch (c) { - case '<': BUFPUTSL(ob, "<"); return 1; - case '>': BUFPUTSL(ob, ">"); return 1; - case '&': BUFPUTSL(ob, "&"); return 1; - case '"': BUFPUTSL(ob, """); return 1; - default: return 0; + case '<': BUFPUTSL(ob, "<"); break; + case '>': BUFPUTSL(ob, ">"); break; + case '&': BUFPUTSL(ob, "&"); break; + case '"': BUFPUTSL(ob, """); break; + default: bufputc(ob, c); break; } } @@ -190,28 +195,34 @@ rndr_codespan(struct buf *ob, struct buf *text, void *opaque) } static int -rndr_double_emphasis(struct buf *ob, struct buf *text, char c, void *opaque) +rndr_strikethrough(struct buf *ob, struct buf *text, void *opaque) { if (!text || !text->size) return 0; - if (c == '~') { - BUFPUTSL(ob, ""); - bufput(ob, text->data, text->size); - BUFPUTSL(ob, ""); - } else { - BUFPUTSL(ob, ""); - bufput(ob, text->data, text->size); - BUFPUTSL(ob, ""); - } + BUFPUTSL(ob, ""); + bufput(ob, text->data, text->size); + BUFPUTSL(ob, ""); + return 1; +} + +static int +rndr_double_emphasis(struct buf *ob, 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_emphasis(struct buf *ob, struct buf *text, char c, void *opaque) +rndr_emphasis(struct buf *ob, struct buf *text, void *opaque) { - if (!text || !text->size || c == '~') return 0; + if (!text || !text->size) return 0; BUFPUTSL(ob, ""); if (text) bufput(ob, text->data, text->size); BUFPUTSL(ob, ""); @@ -311,6 +322,10 @@ rndr_paragraph(struct buf *ob, struct buf *text, void *opaque) bufput(ob, &text->data[i], text->size - i); } BUFPUTSL(ob, "

\n"); + + /* Close any open quotes at the end of the paragraph */ + options->quotes.in_squote = 0; + options->quotes.in_dquote = 0; } static void @@ -329,7 +344,7 @@ rndr_raw_block(struct buf *ob, struct buf *text, void *opaque) } static int -rndr_triple_emphasis(struct buf *ob, struct buf *text, char c, void *opaque) +rndr_triple_emphasis(struct buf *ob, struct buf *text, void *opaque) { if (!text || !text->size) return 0; BUFPUTSL(ob, ""); @@ -546,8 +561,8 @@ rndr_normal_text(struct buf *ob, struct buf *text, void *opaque) static void rndr_smartypants(struct buf *ob, struct buf *text, void *opaque) { + struct xhtml_renderopt *options = opaque; size_t i; - int open_single = 0, open_double = 0, open_tag = 0; if (!text) return; @@ -572,78 +587,17 @@ rndr_smartypants(struct buf *ob, struct buf *text, void *opaque) continue; switch (c) { - case '<': - open_tag = 1; - break; - - case '>': - open_tag = 0; - break; - -#if 0 - /* - * FIXME: this is bongos. - * - * The markdown spec defines that code blocks can be delimited - * by more than one backtick, e.g. - * - * ``There is a literal backtick (`) here.`` - *

There is a literal backtick (`) here.

- * - * Obviously, there's no way to differentiate between the start - * of a code block and the start of a quoted string for smartypants - * - * Look at this piece of Python code: - * - * ``result = ''.join(['this', 'is', 'bongos'])`` - * - * This MD expression is clearly ambiguous since it can be parsed as: - * - *

“result = ”.join ...

- * - * Or also as: - * - *

result = ''.join(['this', 'is', 'bongos'])

- * - * Fuck everything about this. This is temporarily disabled, because at GitHub - * it's probably smarter to prioritize code blocks than pretty cutesy punctuation. - * - * The equivalent closing tag for the (``), ('') has also been disabled, because - * it makes no sense to have closing tags without opening tags. - */ - case '`': - if (open_tag == 0) { - if (i + 1 < text->size && text->data[i + 1] == '`') { - BUFPUTSL(ob, "“"); i++; - continue; - } - } - break; -#endif - case '\"': - if (open_tag == 0) { - if (smartypants_quotes(ob, text, i, open_double)) { - open_double = !open_double; - continue; - } + if (smartypants_quotes(ob, text, i, options->quotes.in_dquote)) { + options->quotes.in_dquote = !options->quotes.in_dquote; + continue; } break; case '\'': - if (open_tag == 0) { - -#if 0 /* temporarily disabled, see previous comment */ - if (i + 1 < text->size && text->data[i + 1] == '\'') { - BUFPUTSL(ob, "”"); i++; - continue; - } -#endif - - if (smartypants_quotes(ob, text, i, open_single)) { - open_single = !open_single; - continue; - } + if (smartypants_quotes(ob, text, i, options->quotes.in_squote)) { + options->quotes.in_squote = !options->quotes.in_squote; + continue; } break; } @@ -651,8 +605,7 @@ rndr_smartypants(struct buf *ob, struct buf *text, void *opaque) /* * Copy raw character */ - if (!put_scaped_char(ob, c)) - bufputc(ob, c); + put_scaped_char(ob, c); } } @@ -720,6 +673,7 @@ ups_toc_renderer(struct mkd_renderer *renderer) NULL, NULL, rndr_triple_emphasis, + rndr_strikethrough, NULL, NULL, @@ -763,6 +717,7 @@ ups_xhtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags) rndr_link, rndr_raw_html, rndr_triple_emphasis, + rndr_strikethrough, NULL, rndr_normal_text, diff --git a/lib/redcarpet.rb b/lib/redcarpet.rb index 0e80be88..f2194ba3 100644 --- a/lib/redcarpet.rb +++ b/lib/redcarpet.rb @@ -26,7 +26,7 @@ # end # class Redcarpet - VERSION = '1.10.0' + VERSION = '1.10.1' # Original Markdown formatted text. attr_reader :text diff --git a/redcarpet.gemspec b/redcarpet.gemspec index e2399bf8..4ae2c4d9 100644 --- a/redcarpet.gemspec +++ b/redcarpet.gemspec @@ -1,9 +1,9 @@ Gem::Specification.new do |s| s.name = 'redcarpet' - s.version = '1.10.0' + s.version = '1.10.1' s.summary = "Ruby bindings for libupskirt" s.description = 'A fast and safe Markdown to (X)HTML parser' - s.date = '2011-04-21' + s.date = '2011-04-22' s.email = 'vicent@github.com' s.homepage = 'http://github.com/tanoku/redcarpet' s.has_rdoc = true diff --git a/upskirt b/upskirt index 3118304d..f3fcabda 160000 --- a/upskirt +++ b/upskirt @@ -1 +1 @@ -Subproject commit 3118304d80c0b2f480953de307ec93185ab4c44a +Subproject commit f3fcabda16cc1dcf458a1e4caa77cf384fcd350f