ext/redcarpet/markdown.c in redcarpet-2.0.0b5 vs ext/redcarpet/markdown.c in redcarpet-2.0.0

- old
+ new

@@ -109,10 +109,11 @@ struct link_ref *refs[REF_TABLE_SIZE]; uint8_t active_char[256]; struct stack work_bufs[2]; unsigned int ext_flags; size_t max_nesting; + int in_link_body; }; /*************************** * HELPER FUNCTIONS * ***************************/ @@ -370,11 +371,10 @@ bufput(ob, data + i, end - i); if (end >= size) break; i = end; - /* calling the trigger */ end = markdown_char_ptrs[(int)action](ob, rndr, data + i, i, size - i); if (!end) /* no action from the callback */ end = i + 1; else { i += end; @@ -423,11 +423,10 @@ else bt = 0; i++; } if (i >= size) return tmp_i; - i++; } /* skipping a link */ else if (data[i] == '[') { size_t tmp_i = 0; uint8_t cc; @@ -680,11 +679,11 @@ /* char_escape • '\\' backslash escape */ static size_t char_escape(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) { - static const char *escape_chars = "\\`*_{}[]()#+-.!:|&<>"; + static const char *escape_chars = "\\`*_{}[]()#+-.!:|&<>^~"; struct buf work = { 0, 0, 0, 0 }; if (size > 1) { if (strchr(escape_chars, data[1]) == NULL) return 0; @@ -756,25 +755,32 @@ } static size_t char_autolink_www(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) { - struct buf *link, *link_url; + struct buf *link, *link_url, *link_text; size_t link_len, rewind; - if (!rndr->cb.link) + if (!rndr->cb.link || rndr->in_link_body) return 0; link = rndr_newbuf(rndr, BUFFER_SPAN); if ((link_len = sd_autolink__www(&rewind, link, data, offset, size)) > 0) { link_url = rndr_newbuf(rndr, BUFFER_SPAN); BUFPUTSL(link_url, "http://"); bufput(link_url, link->data, link->size); ob->size -= rewind; - rndr->cb.link(ob, link_url, NULL, link, rndr->opaque); + if (rndr->cb.normal_text) { + link_text = rndr_newbuf(rndr, BUFFER_SPAN); + rndr->cb.normal_text(link_text, link, rndr->opaque); + rndr->cb.link(ob, link_url, NULL, link_text, rndr->opaque); + rndr_popbuf(rndr, BUFFER_SPAN); + } else { + rndr->cb.link(ob, link_url, NULL, link, rndr->opaque); + } rndr_popbuf(rndr, BUFFER_SPAN); } rndr_popbuf(rndr, BUFFER_SPAN); return link_len; @@ -784,11 +790,11 @@ char_autolink_email(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) { struct buf *link; size_t link_len, rewind; - if (!rndr->cb.autolink) + if (!rndr->cb.autolink || rndr->in_link_body) return 0; link = rndr_newbuf(rndr, BUFFER_SPAN); if ((link_len = sd_autolink__email(&rewind, link, data, offset, size)) > 0) { @@ -804,11 +810,11 @@ char_autolink_url(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) { struct buf *link; size_t link_len, rewind; - if (!rndr->cb.autolink) + if (!rndr->cb.autolink || rndr->in_link_body) return 0; link = rndr_newbuf(rndr, BUFFER_SPAN); if ((link_len = sd_autolink__url(&rewind, link, data, offset, size)) > 0) { @@ -830,10 +836,11 @@ struct buf *link = 0; struct buf *title = 0; struct buf *u_link = 0; size_t org_work_size = rndr->work_bufs[BUFFER_SPAN].size; int text_has_nl = 0, ret = 0; + int in_title = 0, qtype = 0; /* checking whether the correct renderer exists */ if ((is_img && !rndr->cb.image) || (!is_img && !rndr->cb.link)) goto cleanup; @@ -886,16 +893,19 @@ if (i >= size) goto cleanup; link_e = i; /* looking for title end if present */ if (data[i] == '\'' || data[i] == '"') { + qtype = data[i]; + in_title = 1; i++; title_b = i; while (i < size) { if (data[i] == '\\') i += 2; - else if (data[i] == ')') break; + else if (data[i] == qtype) {in_title = 0; i++;} + else if ((data[i] == ')') && !in_title) break; else i++; } if (i >= size) goto cleanup; @@ -1017,12 +1027,19 @@ } /* building content: img alt is escaped, link content is parsed */ if (txt_e > 1) { content = rndr_newbuf(rndr, BUFFER_SPAN); - if (is_img) bufput(content, data + 1, txt_e - 1); - else parse_inline(content, rndr, data + 1, txt_e - 1); + if (is_img) { + bufput(content, data + 1, txt_e - 1); + } else { + /* disable autolinking when parsing inline the + * content of a link */ + rndr->in_link_body = 1; + parse_inline(content, rndr, data + 1, txt_e - 1); + rndr->in_link_body = 0; + } } if (link) { u_link = rndr_newbuf(rndr, BUFFER_SPAN); unscape_text(u_link, link); @@ -1556,10 +1573,11 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, int *flags) { struct buf *work = 0, *inter = 0; size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i; int in_empty = 0, has_inside_empty = 0; + int has_next_uli, has_next_oli; /* keeping track of the first indentation prefix */ while (orgpre < 3 && orgpre < size && data[orgpre] == ' ') orgpre++; @@ -1602,14 +1620,24 @@ while (i < 4 && beg + i < end && data[beg + i] == ' ') i++; pre = i; + has_next_uli = prefix_uli(data + beg + i, end - beg - i); + has_next_oli = prefix_oli(data + beg + i, end - beg - i); + + /* checking for ul/ol switch */ + if (in_empty && ( + ((*flags & MKD_LIST_ORDERED) && has_next_uli) || + (!(*flags & MKD_LIST_ORDERED) && has_next_oli) + )){ + *flags |= MKD_LI_END; + break; /* the following item must have same list type */ + } + /* checking for a new item */ - if ((prefix_uli(data + beg + i, end - beg - i) && - !is_hrule(data + beg + i, end - beg - i)) || - prefix_oli(data + beg + i, end - beg - i)) { + if ((has_next_uli && !is_hrule(data + beg + i, end - beg - i)) || has_next_oli) { if (in_empty) has_inside_empty = 1; if (pre == orgpre) /* the following item must have */ break; /* the same indentation */ @@ -2323,9 +2351,10 @@ /* Extension data */ md->ext_flags = extensions; md->opaque = opaque; md->max_nesting = max_nesting; + md->in_link_body = 0; return md; } void