static int rndr_link(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *content, void *opaque) { struct html_renderopt *options = opaque; if (link != NULL && (options->flags & HTML_SAFELINK) != 0 && !sd_autolink_issafe(link->data, link->size)) return 0; BUFPUTSL(ob, "<a href=\""); if (link && link->size) escape_href(ob, link->data, link->size); if (title && title->size) { BUFPUTSL(ob, "\" title=\""); escape_html(ob, title->data, title->size); } if (options->link_attributes) { bufputc(ob, '\"'); options->link_attributes(ob, link, opaque); bufputc(ob, '>'); } else { BUFPUTSL(ob, "\">"); } if (content && content->size) bufput(ob, content->data, content->size); BUFPUTSL(ob, "</a>"); return 1; }
size_t sd_autolink__url(size_t *rewind_p, struct buf *link, uint8_t *data, size_t offset, size_t size) { size_t link_end, rewind = 0, domain_len; if (size < 4 || data[1] != '/' || data[2] != '/') return 0; while (rewind < offset && isalpha(data[-rewind - 1])) rewind++; if (!sd_autolink_issafe(data - rewind, size + rewind)) return 0; link_end = strlen("://"); domain_len = check_domain(data + link_end, size - link_end); if (domain_len == 0) return 0; link_end += domain_len; while (link_end < size && !isspace(data[link_end])) link_end++; link_end = autolink_delim(data, link_end, offset, size); if (link_end == 0) return 0; bufput(link, data - rewind, link_end + rewind); *rewind_p = rewind; return link_end; }
/******************** * GENERIC RENDERER * ********************/ static int rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, void *opaque) { struct html_renderopt *options = opaque; if (!link || !link->size) return 0; if ((options->flags & HTML_SAFELINK) != 0 && !sd_autolink_issafe(link->data, link->size) && type != MKDA_EMAIL) return 0; BUFPUTSL(ob, "<a href=\""); if (type == MKDA_EMAIL) BUFPUTSL(ob, "mailto:"); bufput(ob, link->data, link->size); BUFPUTSL(ob, "\">"); /* * Pretty printing: if we get an email address as * an actual URI, e.g. `mailto:[email protected]`, we don't * want to print the `mailto:` prefix */ if (bufprefix(link, "mailto:") == 0) { sdhtml_escape(ob, link->data + 7, link->size - 7); } else { sdhtml_escape(ob, link->data, link->size); } BUFPUTSL(ob, "</a>"); return 1; }
static int rndr_image(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *alt, void *opaque) { struct html_renderopt *options = opaque; if (link != NULL && (options->flags & HTML_SAFELINK) != 0 && !sd_autolink_issafe(link->data, link->size)) return 0; BUFPUTSL(ob, "<img src=\""); if (link && link->size) escape_href(ob, link->data, link->size); BUFPUTSL(ob, "\" alt=\""); if (alt && alt->size) escape_html(ob, alt->data, alt->size); if (title && title->size) { BUFPUTSL(ob, "\" title=\""); escape_html(ob, title->data, title->size); } bufputs(ob, USE_XHTML(options) ? "\"/>" : "\">"); return 1; }
static cmark_node *url_match(cmark_parser *parser, cmark_node *parent, cmark_inline_parser *inline_parser) { size_t link_end, domain_len; int rewind = 0; cmark_chunk *chunk = cmark_inline_parser_get_chunk(inline_parser); int max_rewind = cmark_inline_parser_get_offset(inline_parser); uint8_t *data = chunk->data + max_rewind; size_t size = chunk->len - max_rewind; if (size < 4 || data[1] != '/' || data[2] != '/') return 0; while (rewind < max_rewind && cmark_isalpha(data[-rewind - 1])) rewind++; if (!sd_autolink_issafe(data - rewind, size + rewind)) return 0; link_end = strlen("://"); domain_len = check_domain(data + link_end, size - link_end, 1); if (domain_len == 0) return 0; link_end += domain_len; while (link_end < size && !cmark_isspace(data[link_end])) link_end++; link_end = autolink_delim(data, link_end); if (link_end == 0) return NULL; cmark_inline_parser_set_offset(inline_parser, (int)(max_rewind + link_end)); cmark_node_unput(parent, rewind); cmark_node *node = cmark_node_new_with_mem(CMARK_NODE_LINK, parser->mem); cmark_chunk url = cmark_chunk_dup(chunk, max_rewind - rewind, (bufsize_t)(link_end + rewind)); node->as.link.url = url; cmark_node *text = cmark_node_new_with_mem(CMARK_NODE_TEXT, parser->mem); text->as.literal = url; cmark_node_append_child(node, text); return node; }
static int rndr_link(struct buf *ob, struct buf *link, struct buf *title, struct buf *content, void *opaque) { struct html_renderopt *options = opaque; if ((options->flags & HTML_SAFELINK) != 0 && !sd_autolink_issafe(link->data, link->size)) return 0; BUFPUTSL(ob, "<a href=\""); if (link && link->size) bufput(ob, link->data, link->size); if (title && title->size) { BUFPUTSL(ob, "\" title=\""); sdhtml_escape(ob, title->data, title->size); } BUFPUTSL(ob, "\">"); if (content && content->size) bufput(ob, content->data, content->size); BUFPUTSL(ob, "</a>"); return 1; }
size_t sd_autolink__url( 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; if (size < 4 || data[1] != '/' || data[2] != '/') return 0; while (rewind < max_rewind && isalpha(data[-rewind - 1])) rewind++; if (!sd_autolink_issafe(data - rewind, size + rewind)) return 0; link_end = strlen("://"); domain_len = check_domain( data + link_end, size - link_end, flags & SD_AUTOLINK_SHORT_DOMAINS); if (domain_len == 0) return 0; link_end += domain_len; while (link_end < size && !isspace(data[link_end])) link_end++; link_end = autolink_delim(data, link_end, max_rewind, size); if (link_end == 0) return 0; bufput(link, data - rewind, link_end + rewind); *rewind_p = rewind; return link_end; }
/******************** * GENERIC RENDERER * ********************/ static int rndr_autolink(struct buf *ob, const struct buf *link, enum mkd_autolink type, void *opaque) { struct html_renderopt *options = opaque; if (!link || !link->size) return 0; if ((options->flags & HTML_SAFELINK) != 0 && !sd_autolink_issafe(link->data, link->size) && type != MKDA_EMAIL) return 0; BUFPUTSL(ob, "<a href=\""); if (type == MKDA_EMAIL) BUFPUTSL(ob, "mailto:"); escape_href(ob, link->data, link->size); if (options->link_attributes) { bufputc(ob, '\"'); options->link_attributes(ob, link, opaque); bufputc(ob, '>'); } else if (options->flags & HTML_NEW_TAB_LINKS) { BUFPUTSL(ob, "\" target=\"_blank\">"); } else { BUFPUTSL(ob, "\">"); } /* * Pretty printing: if we get an email address as * an actual URI, e.g. `mailto:[email protected]`, we don't * want to print the `mailto:` prefix */ if (bufprefix(link, "mailto:") == 0) { escape_html(ob, link->data + 7, link->size - 7); } else { escape_html(ob, link->data, link->size); } BUFPUTSL(ob, "</a>"); return 1; }