/* * GitHub style code block: * * <pre lang="LANG"><code> * ... * </pre></code> * * Unlike other parsers, we store the language identifier in the <pre>, * and don't let the user generate custom classes. * * The language identifier in the <pre> block gets postprocessed and all * the code inside gets syntax highlighted with Pygments. This is much safer * than letting the user specify a CSS class for highlighting. * * Note that we only generate HTML for the first specifier. * E.g. * ~~~~ {.python .numbered} => <pre lang="python"><code> */ static void rndr_blockcode_github(struct buf *ob, struct buf *text, struct buf *lang, void *opaque) { if (ob->size) bufputc(ob, '\n'); if (lang && lang->size) { size_t i = 0; BUFPUTSL(ob, "<pre lang=\""); while (i < lang->size && !isspace(lang->data[i])) i++; if (lang->data[0] == '.') sdhtml_escape(ob, lang->data + 1, i - 1); else sdhtml_escape(ob, lang->data, i); BUFPUTSL(ob, "\"><code>"); } else BUFPUTSL(ob, "<pre><code>"); if (text) sdhtml_escape(ob, text->data, text->size); BUFPUTSL(ob, "</code></pre>\n"); }
static void rndr_blockcode(struct buf *ob, struct buf *text, struct buf *lang, void *opaque) { if (ob->size) bufputc(ob, '\n'); if (lang && lang->size) { size_t i, cls; BUFPUTSL(ob, "<pre><code class=\""); for (i = 0, cls = 0; i < lang->size; ++i, ++cls) { while (i < lang->size && isspace(lang->data[i])) i++; if (i < lang->size) { size_t org = i; while (i < lang->size && !isspace(lang->data[i])) i++; if (lang->data[org] == '.') org++; if (cls) bufputc(ob, ' '); sdhtml_escape(ob, lang->data + org, i - org); } } BUFPUTSL(ob, "\">"); } else BUFPUTSL(ob, "<pre><code>"); if (text) sdhtml_escape(ob, text->data, text->size); BUFPUTSL(ob, "</code></pre>\n"); }
/******************** * 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_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); } 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; }
static int rndr_image(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt, void *opaque) { struct html_renderopt *options = opaque; if (!link || !link->size) return 0; BUFPUTSL(ob, "<img src=\""); sdhtml_escape(ob, link->data, link->size); BUFPUTSL(ob, "\" alt=\""); if (alt && alt->size) sdhtml_escape(ob, alt->data, alt->size); if (title && title->size) { BUFPUTSL(ob, "\" title=\""); sdhtml_escape(ob, title->data, title->size); } bufputs(ob, USE_XHTML(options) ? "\"/>" : "\">"); return 1; }
static int rndr_codespan(struct buf *ob, struct buf *text, void *opaque) { BUFPUTSL(ob, "<code>"); if (text) sdhtml_escape(ob, text->data, text->size); BUFPUTSL(ob, "</code>"); return 1; }
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 && !is_safe_link(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; }
static void rndr_normal_text(struct buf *ob, struct buf *text, void *opaque) { if (text) sdhtml_escape(ob, text->data, text->size); }