Linkify SSB refs

main
cel 5 years ago
parent 57c8c1d88a
commit a1c15a7270

@ -26,12 +26,26 @@
#define strncasecmp _strnicmp #define strncasecmp _strnicmp
#endif #endif
static int
ismentionchar(char c)
{
return isalnum(c) || c == '_' || c == '-' || c == '+' || c == '/' || c == '=';
}
static int
ishashtagend(char c)
{
return isspace(c) || c == '(' || c == ')' || c == '[' || c == ']' ||
c == ',' || c == '.' || c == '"';
}
int int
sd_autolink_issafe(const uint8_t *link, size_t link_len) sd_autolink_issafe(const uint8_t *link, size_t link_len)
{ {
static const size_t valid_uris_count = 8; static const size_t valid_uris_count = 12;
static const char *valid_uris[] = { static const char *valid_uris[] = {
"§", "§",
"@", "&", "%", "#",
"gemini://", "gopher://", "gemini://", "gopher://",
"/", "http://", "https://", "ftp://", "mailto:" "/", "http://", "https://", "ftp://", "mailto:"
}; };
@ -329,3 +343,46 @@ sd_autolink__zet(
return link_end; return link_end;
} }
size_t
sd_autolink__ssb(
size_t *rewind_p,
struct buf *link,
uint8_t *data,
size_t max_rewind,
size_t size,
unsigned int flags)
{
size_t link_end = 1, rewind = 0, domain_len;
char sigil = data[0];
if (sigil == '#') {
while (link_end < size && isdigit(data[link_end]))
link_end++;
if (link_end < size && (isspace(data[link_end]) ||
ispunct(data[link_end])))
return 0;
while (link_end < size && !ishashtagend(data[link_end]))
link_end++;
} else {
if (sigil != '%' && sigil != '@' && sigil != '&')
return 0;
while (link_end < size && (ismentionchar(data[link_end]) || data[link_end] == '.'))
link_end++;
if (ispunct(data[link_end-1]))
link_end--;
if (link_end < 2)
return 0;
}
bufput(link, data - rewind, link_end + rewind);
*rewind_p = rewind;
return link_end;
}

@ -46,6 +46,10 @@ size_t
sd_autolink__zet(size_t *rewind_p, struct buf *link, sd_autolink__zet(size_t *rewind_p, struct buf *link,
uint8_t *data, size_t offset, size_t size, unsigned int flags); uint8_t *data, size_t offset, size_t size, unsigned int flags);
size_t
sd_autolink__ssb(size_t *rewind_p, struct buf *link,
uint8_t *data, size_t offset, size_t size, unsigned int flags);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -71,7 +71,9 @@ static size_t char_entity(struct buf *ob, struct sd_markdown *rndr, uint8_t *dat
static size_t char_langle_tag(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size); static size_t char_langle_tag(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
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_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_email(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
static size_t char_autolink_at(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_www(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
static size_t char_autolink_ssb(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_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_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); static size_t char_superscript(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
@ -86,8 +88,9 @@ enum markdown_char_t {
MD_CHAR_ESCAPE, MD_CHAR_ESCAPE,
MD_CHAR_ENTITITY, MD_CHAR_ENTITITY,
MD_CHAR_AUTOLINK_URL, MD_CHAR_AUTOLINK_URL,
MD_CHAR_AUTOLINK_EMAIL, MD_CHAR_AUTOLINK_AT,
MD_CHAR_AUTOLINK_WWW, MD_CHAR_AUTOLINK_WWW,
MD_CHAR_AUTOLINK_SSB,
MD_CHAR_AUTOLINK_ZET, MD_CHAR_AUTOLINK_ZET,
MD_CHAR_SUPERSCRIPT, MD_CHAR_SUPERSCRIPT,
}; };
@ -102,8 +105,9 @@ static char_trigger markdown_char_ptrs[] = {
&char_escape, &char_escape,
&char_entity, &char_entity,
&char_autolink_url, &char_autolink_url,
&char_autolink_email, &char_autolink_at,
&char_autolink_www, &char_autolink_www,
&char_autolink_ssb,
&char_autolink_zet, &char_autolink_zet,
&char_superscript, &char_superscript,
}; };
@ -817,6 +821,17 @@ char_autolink_email(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, siz
return link_len; return link_len;
} }
static size_t
char_autolink_at(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
{
size_t link_len;
link_len = char_autolink_ssb(ob, rndr, data, offset, size);
if (link_len) return link_len;
return char_autolink_email(ob, rndr, data, offset, size);
}
static size_t static size_t
char_autolink_url(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) char_autolink_url(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
{ {
@ -837,6 +852,26 @@ char_autolink_url(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_
return link_len; return link_len;
} }
static size_t
char_autolink_ssb(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 || rndr->in_link_body)
return 0;
link = rndr_newbuf(rndr, BUFFER_SPAN);
if ((link_len = sd_autolink__ssb(&rewind, link, data, offset, size, 0)) > 0) {
ob->size -= rewind;
rndr->cb.autolink(ob, link, MKDA_SSB, rndr->opaque);
}
rndr_popbuf(rndr, BUFFER_SPAN);
return link_len;
}
static size_t static size_t
char_autolink_zet(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size) char_autolink_zet(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
{ {
@ -2457,8 +2492,11 @@ sd_markdown_new(
if (extensions & MKDEXT_AUTOLINK) { if (extensions & MKDEXT_AUTOLINK) {
md->active_char[':'] = MD_CHAR_AUTOLINK_URL; md->active_char[':'] = MD_CHAR_AUTOLINK_URL;
md->active_char['@'] = MD_CHAR_AUTOLINK_EMAIL; md->active_char['@'] = MD_CHAR_AUTOLINK_AT;
md->active_char['w'] = MD_CHAR_AUTOLINK_WWW; md->active_char['w'] = MD_CHAR_AUTOLINK_WWW;
md->active_char['%'] = MD_CHAR_AUTOLINK_SSB;
md->active_char['&'] = MD_CHAR_AUTOLINK_SSB;
md->active_char['#'] = MD_CHAR_AUTOLINK_SSB;
md->active_char[194] = MD_CHAR_AUTOLINK_ZET; md->active_char[194] = MD_CHAR_AUTOLINK_ZET;
} }

@ -40,7 +40,8 @@ enum mkd_autolink {
MKDA_NOT_AUTOLINK, /* used internally when it is not an autolink*/ MKDA_NOT_AUTOLINK, /* used internally when it is not an autolink*/
MKDA_NORMAL, /* normal http/http/ftp/mailto/etc link */ MKDA_NORMAL, /* normal http/http/ftp/mailto/etc link */
MKDA_EMAIL, /* e-mail link without explit mailto: */ MKDA_EMAIL, /* e-mail link without explit mailto: */
MKDA_ZET, /* zet link */ MKDA_SSB, /* ssb link */
MKDA_ZET, /* zet link */
}; };
enum mkd_tableflags { enum mkd_tableflags {

@ -27,6 +27,9 @@
static const size_t sigil_size = sizeof("§")-1; static const size_t sigil_size = sizeof("§")-1;
static const int id_length = 16; static const int id_length = 16;
static const char ssb_ref_base[] = "http://localhost:8027/";
static const char ssb_channel_base[] = "http://localhost:8027/channel/";
static const int max_cols = 40; static const int max_cols = 40;
static char server_hostname[256]; static char server_hostname[256];
@ -473,7 +476,14 @@ md_rndr_link(struct buf *ob, const struct buf *link, const struct buf *title, co
if (!strncmp((char *)link->data, "§", sigil_size)) if (!strncmp((char *)link->data, "§", sigil_size))
houdini_escape_href(ob, link->data + sigil_size, houdini_escape_href(ob, link->data + sigil_size,
link->size - sigil_size); link->size - sigil_size);
else if (link->data[0] == '#') {
BUFPUTSL(ob, ssb_channel_base);
houdini_escape_href(ob, link->data + 1, link->size - 1);
} else if (link->data[0] == '#' || link->data[0] == '@'
|| link->data[0] == '&' || link->data[0] == '%') {
BUFPUTSL(ob, ssb_ref_base);
houdini_escape_href(ob, link->data, link->size);
} else
houdini_escape_href(ob, link->data, link->size); houdini_escape_href(ob, link->data, link->size);
} }
@ -495,12 +505,13 @@ md_rndr_link(struct buf *ob, const struct buf *link, const struct buf *title, co
return 1; return 1;
} }
static void put_link_truncated(struct buf *ob, const struct buf *link) { static void put_link_truncated(struct buf *ob, const struct buf *link, int max_length) {
if (link->size < max_cols) { if (link->size > max_length) {
return houdini_escape_html0(ob, link->data, link->size, 0); houdini_escape_html0(ob, link->data, max_length, 0);
BUFPUTSL(ob, "");
} else {
houdini_escape_html0(ob, link->data, link->size, 0);
} }
houdini_escape_html0(ob, link->data, max_cols, 0);
BUFPUTSL(ob, "");
} }
static int static int
@ -521,7 +532,15 @@ md_rndr_autolink(struct buf *ob, const struct buf *link, enum mkd_autolink type,
BUFPUTSL(ob, "mailto:"); BUFPUTSL(ob, "mailto:");
if (type == MKDA_ZET) if (type == MKDA_ZET)
houdini_escape_href(ob, link->data + sigil_size, link->size - sigil_size); houdini_escape_href(ob, link->data + sigil_size, link->size - sigil_size);
else else if (type == MKDA_SSB) {
if (link->data[0] == '#') {
BUFPUTSL(ob, ssb_channel_base);
houdini_escape_href(ob, link->data + 1, link->size - 1);
} else {
BUFPUTSL(ob, ssb_ref_base);
houdini_escape_href(ob, link->data, link->size);
}
} else
houdini_escape_href(ob, link->data, link->size); houdini_escape_href(ob, link->data, link->size);
if (type == MKDA_ZET) { if (type == MKDA_ZET) {
@ -548,8 +567,10 @@ md_rndr_autolink(struct buf *ob, const struct buf *link, enum mkd_autolink type,
*/ */
if (bufprefix(link, "mailto:") == 0) { if (bufprefix(link, "mailto:") == 0) {
houdini_escape_html0(ob, link->data + 7, link->size - 7, 0); houdini_escape_html0(ob, link->data + 7, link->size - 7, 0);
} else if (link->data[0] == '&' || link->data[0] == '@' || link->data[0] == '%') {
put_link_truncated(ob, link, 8);
} else { } else {
put_link_truncated(ob, link); put_link_truncated(ob, link, max_cols);
} }
BUFPUTSL(ob, "</a>"); BUFPUTSL(ob, "</a>");

Loading…
Cancel
Save