autolinking: fix bugs
This commit is contained in:
parent
cbb7fb53c6
commit
8af37fd1b4
3 changed files with 99 additions and 100 deletions
|
@ -70,13 +70,18 @@ skip_tags(struct buf *ob, const char *text, size_t size)
|
|||
}
|
||||
|
||||
bufput(ob, text, i + 1);
|
||||
return i;
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
void
|
||||
upshtml_autolink(struct buf *ob, struct buf *text, unsigned int flags)
|
||||
upshtml_autolink(
|
||||
struct buf *ob,
|
||||
struct buf *text,
|
||||
unsigned int flags,
|
||||
void (*link_text_cb)(struct buf *ob, const struct buf *link, void *payload),
|
||||
void *payload)
|
||||
{
|
||||
size_t i;
|
||||
size_t i, end;
|
||||
struct buf *link = bufnew(16);
|
||||
const char *active_chars;
|
||||
|
||||
|
@ -101,72 +106,76 @@ upshtml_autolink(struct buf *ob, struct buf *text, unsigned int flags)
|
|||
|
||||
bufgrow(ob, text->size);
|
||||
|
||||
for (i = 0; i < text->size; ++i) {
|
||||
size_t org, rewind, link_size;
|
||||
i = end = 0;
|
||||
|
||||
org = i;
|
||||
while (i < text->size && strchr(active_chars, text->data[i]) == NULL)
|
||||
i++;
|
||||
while (i < text->size) {
|
||||
size_t rewind;
|
||||
|
||||
if (i > org)
|
||||
bufput(ob, text->data + org, i - org);
|
||||
while (end < text->size && strchr(active_chars, text->data[end]) == NULL)
|
||||
end++;
|
||||
|
||||
if (i == text->size)
|
||||
bufput(ob, text->data + i, end - i);
|
||||
|
||||
if (end >= text->size)
|
||||
break;
|
||||
|
||||
i = end;
|
||||
link->size = 0;
|
||||
|
||||
switch (text->data[i]) {
|
||||
case '@':
|
||||
link_size = ups_autolink__email(&rewind, link, text->data + i, i, text->size - i);
|
||||
if (link_size == 0)
|
||||
break;
|
||||
|
||||
ob->size -= rewind;
|
||||
BUFPUTSL(ob, "<a href=\"mailto:");
|
||||
bufput(ob, link->data, link->size);
|
||||
BUFPUTSL(ob, "\">");
|
||||
upshtml_escape(ob, link->data, link->size);
|
||||
BUFPUTSL(ob, "</a>");
|
||||
|
||||
i += link_size;
|
||||
continue;
|
||||
end = ups_autolink__email(&rewind, link, text->data + i, i, text->size - i);
|
||||
if (end > 0) {
|
||||
ob->size -= rewind;
|
||||
BUFPUTSL(ob, "<a href=\"mailto:");
|
||||
bufput(ob, link->data, link->size);
|
||||
BUFPUTSL(ob, "\">");
|
||||
if (link_text_cb) callback(ob, link, payload);
|
||||
else upshtml_escape(ob, link->data, link->size);
|
||||
BUFPUTSL(ob, "</a>");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
link_size = ups_autolink__www(&rewind, link, text->data + i, i, text->size - i);
|
||||
if (link_size == 0)
|
||||
break;
|
||||
|
||||
BUFPUTSL(ob, "<a href=\"http://");
|
||||
bufput(ob, link->data, link->size);
|
||||
BUFPUTSL(ob, "\">");
|
||||
upshtml_escape(ob, link->data, link->size);
|
||||
BUFPUTSL(ob, "</a>");
|
||||
|
||||
i += link_size;
|
||||
continue;
|
||||
end = ups_autolink__www(&rewind, link, text->data + i, i, text->size - i);
|
||||
if (end > 0) {
|
||||
BUFPUTSL(ob, "<a href=\"http://");
|
||||
bufput(ob, link->data, link->size);
|
||||
BUFPUTSL(ob, "\">");
|
||||
if (link_text_cb) callback(ob, link, payload);
|
||||
else upshtml_escape(ob, link->data, link->size);
|
||||
BUFPUTSL(ob, "</a>");
|
||||
}
|
||||
break;
|
||||
|
||||
case ':':
|
||||
link_size = ups_autolink__url(&rewind, link, text->data + i, i, text->size - i);
|
||||
if (link_size == 0)
|
||||
break;
|
||||
|
||||
ob->size -= rewind;
|
||||
BUFPUTSL(ob, "<a href=\"");
|
||||
bufput(ob, link->data, link->size);
|
||||
BUFPUTSL(ob, "\">");
|
||||
upshtml_escape(ob, link->data, link->size);
|
||||
BUFPUTSL(ob, "</a>");
|
||||
|
||||
i += link_size;
|
||||
continue;
|
||||
end = ups_autolink__url(&rewind, link, text->data + i, i, text->size - i);
|
||||
if (end > 0) {
|
||||
ob->size -= rewind;
|
||||
BUFPUTSL(ob, "<a href=\"");
|
||||
bufput(ob, link->data, link->size);
|
||||
BUFPUTSL(ob, "\">");
|
||||
if (link_text_cb) callback(ob, link, payload);
|
||||
else upshtml_escape(ob, link->data, link->size);
|
||||
BUFPUTSL(ob, "</a>");
|
||||
}
|
||||
break;
|
||||
|
||||
case '<':
|
||||
i += skip_tags(ob, text->data + i, text->size - i);
|
||||
continue;
|
||||
end = skip_tags(ob, text->data + i, text->size - i);
|
||||
break;
|
||||
|
||||
default:
|
||||
end = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
bufputc(ob, text->data[i]);
|
||||
if (!end)
|
||||
end = i + 1;
|
||||
else {
|
||||
i += end;
|
||||
end = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,36 +49,32 @@ autolink_delim(char *data, size_t link_end, size_t offset, size_t size)
|
|||
{
|
||||
char cclose, copen = 0;
|
||||
|
||||
/* See if the link finishes with a punctuation sign that can be skipped. */
|
||||
switch (data[link_end - 1]) {
|
||||
case '?':
|
||||
case '!':
|
||||
case '.':
|
||||
case ',':
|
||||
link_end--;
|
||||
break;
|
||||
}
|
||||
|
||||
if (data[link_end - 1] == ';') {
|
||||
size_t new_end = link_end - 2;
|
||||
|
||||
while (new_end > 0 && isalpha(data[new_end]))
|
||||
new_end--;
|
||||
|
||||
if (new_end < link_end - 2 && data[new_end] == '&')
|
||||
link_end = new_end;
|
||||
else
|
||||
link_end--;
|
||||
}
|
||||
|
||||
if (data[link_end - 1] == '>') {
|
||||
while (link_end > 0 && data[link_end] != '<')
|
||||
while (link_end > 0) {
|
||||
if (strchr("?!.,", data[link_end - 1]) != NULL)
|
||||
link_end--;
|
||||
|
||||
if (link_end == 0)
|
||||
return 0;
|
||||
else if (data[link_end - 1] == ';') {
|
||||
size_t new_end = link_end - 2;
|
||||
|
||||
while (new_end > 0 && isalpha(data[new_end]))
|
||||
new_end--;
|
||||
|
||||
if (new_end < link_end - 2 && data[new_end] == '&')
|
||||
link_end = new_end;
|
||||
else
|
||||
link_end--;
|
||||
}
|
||||
|
||||
else if (data[link_end - 1] == '>') {
|
||||
while (link_end > 0 && data[link_end] != '<')
|
||||
link_end--;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
if (link_end == 0)
|
||||
return 0;
|
||||
|
||||
cclose = data[link_end - 1];
|
||||
|
||||
switch (cclose) {
|
||||
|
|
|
@ -719,19 +719,17 @@ char_autolink_www(struct buf *ob, struct render *rndr, char *data, size_t offset
|
|||
|
||||
link = rndr_newbuf(rndr, BUFFER_SPAN);
|
||||
|
||||
if ((link_len = ups_autolink__www(&rewind, link, data, offset, size)) == 0)
|
||||
return 0;
|
||||
if ((link_len = ups_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);
|
||||
|
||||
link_url = rndr_newbuf(rndr, BUFFER_SPAN);
|
||||
BUFPUTSL(link_url, "http://");
|
||||
bufput(link_url, link->data, link->size);
|
||||
|
||||
ob->size -= rewind;
|
||||
rndr->make.link(ob, link_url, NULL, link, rndr->make.opaque);
|
||||
ob->size -= rewind;
|
||||
rndr->make.link(ob, link_url, NULL, link, rndr->make.opaque);
|
||||
rndr_popbuf(rndr, BUFFER_SPAN);
|
||||
}
|
||||
|
||||
rndr_popbuf(rndr, BUFFER_SPAN);
|
||||
rndr_popbuf(rndr, BUFFER_SPAN);
|
||||
|
||||
return link_len;
|
||||
}
|
||||
|
||||
|
@ -746,14 +744,12 @@ char_autolink_email(struct buf *ob, struct render *rndr, char *data, size_t offs
|
|||
|
||||
link = rndr_newbuf(rndr, BUFFER_SPAN);
|
||||
|
||||
if ((link_len = ups_autolink__email(&rewind, link, data, offset, size)) == 0)
|
||||
return 0;
|
||||
|
||||
ob->size -= rewind;
|
||||
rndr->make.autolink(ob, link, MKDA_EMAIL, rndr->make.opaque);
|
||||
if ((link_len = ups_autolink__email(&rewind, link, data, offset, size)) > 0) {
|
||||
ob->size -= rewind;
|
||||
rndr->make.autolink(ob, link, MKDA_EMAIL, rndr->make.opaque);
|
||||
}
|
||||
|
||||
rndr_popbuf(rndr, BUFFER_SPAN);
|
||||
|
||||
return link_len;
|
||||
}
|
||||
|
||||
|
@ -768,14 +764,12 @@ char_autolink_url(struct buf *ob, struct render *rndr, char *data, size_t offset
|
|||
|
||||
link = rndr_newbuf(rndr, BUFFER_SPAN);
|
||||
|
||||
if ((link_len = ups_autolink__url(&rewind, link, data, offset, size)) == 0)
|
||||
return 0;
|
||||
|
||||
ob->size -= rewind;
|
||||
rndr->make.autolink(ob, link, MKDA_NORMAL, rndr->make.opaque);
|
||||
if ((link_len = ups_autolink__url(&rewind, link, data, offset, size)) > 0) {
|
||||
ob->size -= rewind;
|
||||
rndr->make.autolink(ob, link, MKDA_NORMAL, rndr->make.opaque);
|
||||
}
|
||||
|
||||
rndr_popbuf(rndr, BUFFER_SPAN);
|
||||
|
||||
return link_len;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue