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