/* * 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] == '.') attr_escape(ob, lang->data + 1, i - 1); else attr_escape(ob, lang->data, i); BUFPUTSL(ob, "\"><code>"); } else BUFPUTSL(ob, "<pre><code>"); if (text) attr_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, ' '); attr_escape(ob, lang->data + org, i - org); } } BUFPUTSL(ob, "\">"); } else BUFPUTSL(ob, "<pre><code>"); if (text) attr_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 && !is_safe_link(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) { attr_escape(ob, link->data + 7, link->size - 7); } else { attr_escape(ob, link->data, link->size); } BUFPUTSL(ob, "</a>"); return 1; }
static int rndr_image(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt, void *opaque) { if (!link || !link->size) return 0; BUFPUTSL(ob, "<img src=\""); attr_escape(ob, link->data, link->size); BUFPUTSL(ob, "\" alt=\""); if (alt && alt->size) attr_escape(ob, alt->data, alt->size); if (title && title->size) { BUFPUTSL(ob, "\" title=\""); attr_escape(ob, title->data, title->size); } BUFPUTSL(ob, "\" />"); return 1; }
static int rndr_raw_html(struct buf *ob, struct buf *text, void *opaque) { struct xhtml_renderopt *options = opaque; int escape_html = 0; if (options->flags & XHTML_SKIP_HTML) escape_html = 1; else if ((options->flags & XHTML_SKIP_STYLE) != 0 && is_html_tag(text, "style")) escape_html = 1; else if ((options->flags & XHTML_SKIP_LINKS) != 0 && is_html_tag(text, "a")) escape_html = 1; else if ((options->flags & XHTML_SKIP_IMAGES) != 0 && is_html_tag(text, "img")) escape_html = 1; if (escape_html) attr_escape(ob, text->data, text->size); else bufput(ob, text->data, text->size); return 1; }
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 = 0; BUFPUTSL(ob, "<pre><code class=\""); for (i = 0; i < lang->size; ++i) { if (lang->data[i] == '.' && (i == 0 || isspace(lang->data[i - 1]))) continue; bufputc(ob, lang->data[i]); } BUFPUTSL(ob, "\">"); } else BUFPUTSL(ob, "<pre><code>"); if (text) attr_escape(ob, text->data, text->size); BUFPUTSL(ob, "</code></pre>\n"); }
static int rndr_codespan(struct buf *ob, struct buf *text, void *opaque) { BUFPUTSL(ob, "<code>"); if (text) attr_escape(ob, text->data, text->size); BUFPUTSL(ob, "</code>"); 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=\""); attr_escape(ob, link->data, link->size); BUFPUTSL(ob, "\" alt=\""); if (alt && alt->size) attr_escape(ob, alt->data, alt->size); if (title && title->size) { BUFPUTSL(ob, "\" title=\""); attr_escape(ob, title->data, title->size); } bufputc(ob, '"'); bufputs(ob, options->close_tag); 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=\""); attr_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) attr_escape(ob, text->data, text->size); }