From f9a6ebff9c4d4856acdef61a640676281b1c8e60 Mon Sep 17 00:00:00 2001 From: cel Date: Wed, 27 May 2020 21:23:02 -0400 Subject: [PATCH] Auto-linkify note links --- sundown/autolink.c | 35 ++++++++++++++++++++++++++++++++++- sundown/autolink.h | 4 ++++ sundown/html.c | 7 ++++++- sundown/markdown.c | 24 ++++++++++++++++++++++++ sundown/markdown.h | 1 + 5 files changed, 69 insertions(+), 2 deletions(-) diff --git a/sundown/autolink.c b/sundown/autolink.c index 6f8d6ab..b24b0eb 100644 --- a/sundown/autolink.c +++ b/sundown/autolink.c @@ -29,8 +29,9 @@ int sd_autolink_issafe(const uint8_t *link, size_t link_len) { - static const size_t valid_uris_count = 5; + static const size_t valid_uris_count = 6; static const char *valid_uris[] = { + "§", "/", "http://", "https://", "ftp://", "mailto:" }; @@ -295,3 +296,35 @@ sd_autolink__url( return link_end; } +size_t +sd_autolink__zet( + size_t *rewind_p, + struct buf *link, + uint8_t *data, + size_t max_rewind, + size_t size, + unsigned int flags) +{ + size_t link_end, rewind = 0, domain_len; + + static const char sigil_size = sizeof("§")-1; + + if (size < sigil_size || strncmp(data, "§", sigil_size)) + return 0; + + while (rewind < max_rewind && isalpha(data[-rewind - 1])) + rewind++; + + if (!sd_autolink_issafe(data - rewind, size + rewind)) + return 0; + + link_end = sigil_size; + + while (link_end < size && isxdigit(data[link_end])) + link_end++; + + bufput(link, data - rewind, link_end + rewind); + *rewind_p = rewind; + + return link_end; +} diff --git a/sundown/autolink.h b/sundown/autolink.h index 65e0fe6..8593659 100644 --- a/sundown/autolink.h +++ b/sundown/autolink.h @@ -42,6 +42,10 @@ size_t sd_autolink__url(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size, unsigned int flags); +size_t +sd_autolink__zet(size_t *rewind_p, struct buf *link, + uint8_t *data, size_t offset, size_t size, unsigned int flags); + #ifdef __cplusplus } #endif diff --git a/sundown/html.c b/sundown/html.c index 7f08ee8..d53e97e 100755 --- a/sundown/html.c +++ b/sundown/html.c @@ -86,10 +86,15 @@ rndr_autolink(struct buf *ob, const struct buf *link, enum mkd_autolink type, vo type != MKDA_EMAIL) return 0; + static const char zet_sigil_size = sizeof("§")-1; + BUFPUTSL(ob, "data, link->size); + if (type == MKDA_ZET) + escape_href(ob, link->data + zet_sigil_size, link->size - zet_sigil_size); + else + escape_href(ob, link->data, link->size); if (options->link_attributes) { bufputc(ob, '\"'); diff --git a/sundown/markdown.c b/sundown/markdown.c index ea3cf23..3f6c906 100644 --- a/sundown/markdown.c +++ b/sundown/markdown.c @@ -72,6 +72,7 @@ static size_t char_langle_tag(struct buf *ob, struct sd_markdown *rndr, uint8_t static size_t char_autolink_url(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size); static size_t char_autolink_email(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size); static size_t char_autolink_www(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size); +static size_t char_autolink_zet(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size); static size_t char_link(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size); static size_t char_superscript(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size); @@ -87,6 +88,7 @@ enum markdown_char_t { MD_CHAR_AUTOLINK_URL, MD_CHAR_AUTOLINK_EMAIL, MD_CHAR_AUTOLINK_WWW, + MD_CHAR_AUTOLINK_ZET, MD_CHAR_SUPERSCRIPT, }; @@ -102,6 +104,7 @@ static char_trigger markdown_char_ptrs[] = { &char_autolink_url, &char_autolink_email, &char_autolink_www, + &char_autolink_zet, &char_superscript, }; @@ -837,6 +840,26 @@ char_autolink_url(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_ return link_len; } +static size_t +char_autolink_zet(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.link || rndr->in_link_body) + return 0; + + link = rndr_newbuf(rndr, BUFFER_SPAN); + + if ((link_len = sd_autolink__zet(&rewind, link, data, offset, size, 0)) > 0) { + ob->size -= rewind; + rndr->cb.autolink(ob, link, MKDA_ZET, rndr->opaque); + } + + rndr_popbuf(rndr, BUFFER_SPAN); + return link_len; +} + /* char_link • '[': parsing a link or an image */ static size_t char_link(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) @@ -2439,6 +2462,7 @@ sd_markdown_new( md->active_char[':'] = MD_CHAR_AUTOLINK_URL; md->active_char['@'] = MD_CHAR_AUTOLINK_EMAIL; md->active_char['w'] = MD_CHAR_AUTOLINK_WWW; + md->active_char[194] = MD_CHAR_AUTOLINK_ZET; } if (extensions & MKDEXT_SUPERSCRIPT) diff --git a/sundown/markdown.h b/sundown/markdown.h index 6f6553e..6e280d9 100644 --- a/sundown/markdown.h +++ b/sundown/markdown.h @@ -40,6 +40,7 @@ enum mkd_autolink { MKDA_NOT_AUTOLINK, /* used internally when it is not an autolink*/ MKDA_NORMAL, /* normal http/http/ftp/mailto/etc link */ MKDA_EMAIL, /* e-mail link without explit mailto: */ + MKDA_ZET, /* zet link */ }; enum mkd_tableflags {