/* print out a linky (or fail if it's Not Allowed) */ static int linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref) { linkytype *tag; if ( image ) tag = &imaget; else if ( tag = pseudo(ref->link) ) { if ( f->flags & (NO_PSEUDO_PROTO|SAFELINK) ) return 0; } else if ( (f->flags & SAFELINK) && T(ref->link) && (T(ref->link)[0] != '/') && !isautoprefix(T(ref->link)) ) /* if SAFELINK, only accept links that are local or * a well-known protocol */ return 0; else tag = &linkt; if ( f->flags & tag->flags ) return 0; if ( tag->link_pfx ) { Qstring(tag->link_pfx, f); if ( tag->kind & IS_URL ) { if ( f->base && T(ref->link) && (T(ref->link)[tag->szpat] == '/') ) puturl(f->base, strlen(f->base), f, 0); puturl(T(ref->link) + tag->szpat, S(ref->link) - tag->szpat, f, 0); } else ___mkd_reparse(T(ref->link) + tag->szpat, S(ref->link) - tag->szpat, INSIDE_TAG, f); Qstring(tag->link_sfx, f); if ( tag->WxH && ref->height && ref->width ) { Qprintf(f," height=\"%d\"", ref->height); Qprintf(f, " width=\"%d\"", ref->width); } if ( S(ref->title) ) { Qstring(" title=\"", f); ___mkd_reparse(T(ref->title), S(ref->title), INSIDE_TAG, f); Qchar('"', f); } Qstring(tag->text_pfx, f); ___mkd_reparse(T(text), S(text), tag->flags, f); Qstring(tag->text_sfx, f); } else Qwrite(T(ref->link) + tag->szpat, S(ref->link) - tag->szpat, f); return 1; } /* linkyformat */
/* print out a linky (or fail if it's Not Allowed) */ static int linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref) { linkytype *tag; if ( image ) tag = &imaget; else if ( tag = pseudo(ref->link) ) { if ( f->flags & (MKD_NO_EXT|MKD_SAFELINK) ) return 0; } else if ( (f->flags & MKD_SAFELINK) && T(ref->link) && (T(ref->link)[0] != '/') && !isautoprefix(T(ref->link), S(ref->link)) ) /* if MKD_SAFELINK, only accept links that are local or * a well-known protocol */ return 0; else tag = &linkt; if ( f->flags & tag->flags ) return 0; if ( f->flags & IS_LABEL ) ___mkd_reparse(T(text), S(text), tag->flags, f); else if ( tag->link_pfx ) { printlinkyref(f, tag, T(ref->link), S(ref->link)); if ( tag->WxH ) { if ( ref->height ) Qprintf(f," height=\"%d\"", ref->height); if ( ref->width ) Qprintf(f, " width=\"%d\"", ref->width); } if ( S(ref->title) ) { Qstring(" title=\"", f); ___mkd_reparse(T(ref->title), S(ref->title), MKD_TAGTEXT, f); Qchar('"', f); } Qstring(tag->text_pfx, f); ___mkd_reparse(T(text), S(text), tag->flags, f); Qstring(tag->text_sfx, f); } else Qwrite(T(ref->link) + tag->szpat, S(ref->link) - tag->szpat, f); return 1; } /* linkyformat */
static int splat(Line *p, char *block, Istring align, int force, MMIOT *f) { int first, idx = 0, colno = 0; Qstring("<tr>\n", f); while ( idx < S(p->text) ) { first = idx; if ( force && (colno >= S(align)-1) ) idx = S(p->text); else while ( (idx < S(p->text)) && (T(p->text)[idx] != '|') ) ++idx; Qprintf(f, "<%s%s>", block, alignments[ (colno < S(align)) ? T(align)[colno]:0 ]); ___mkd_reparse(T(p->text)+first, idx-first, 0, f); Qprintf(f, "</%s>\n", block); idx++; colno++; } if ( force ) while (colno < S(align) ) { Qprintf(f, "<%s></%s>\n", block, block); ++colno; } Qstring("</tr>\n", f); return colno; }
/* print out the start of an `img' or `a' tag, applying callbacks as needed. */ static void printlinkyref(MMIOT *f, linkytype *tag, char *link, int size) { char *edit; if ( f->flags & IS_LABEL ) return; Qstring(tag->link_pfx, f); if ( tag->kind & IS_URL ) { if ( f->cb && f->cb->e_url && (edit = (*f->cb->e_url)(link, size, f->cb->e_data)) ) { puturl(edit, strlen(edit), f, 0); if ( f->cb->e_free ) (*f->cb->e_free)(edit, f->cb->e_data); } else puturl(link + tag->szpat, size - tag->szpat, f, 0); } else ___mkd_reparse(link + tag->szpat, size - tag->szpat, MKD_TAGTEXT, f, 0); Qstring(tag->link_sfx, f); if ( f->cb && f->cb->e_flags && (edit = (*f->cb->e_flags)(link, size, f->cb->e_data)) ) { Qchar(' ', f); Qstring(edit, f); if ( f->cb->e_free ) (*f->cb->e_free)(edit, f->cb->e_data); } } /* printlinkyref */
/* delspan() -- write out a chunk of text, blocking with <del>...</del> */ static void delspan(MMIOT *f, int size) { Qstring("<del>", f); ___mkd_reparse(cursor(f)-1, size, 0, f); Qstring("</del>", f); }
static void definitionlist(Paragraph *p, MMIOT *f) { Line *tag; if ( p ) { Qstring("<dl>\n", f); for ( ; p ; p = p->next) { for ( tag = p->text; tag; tag = tag->next ) { Qstring("<dt>", f); ___mkd_reparse(T(tag->text), S(tag->text), 0, f); Qstring("</dt>\n", f); } // MK HACK if (p->down) { p->down->easyNewline = p->easyNewline; } htmlify(p->down, "dd", p->ident, f); Qchar('\n', f); } Qstring("</dl>", f); } }
/* ___mkd_reparse() a line */ static void mkd_parse_line(char *bfr, int size, MMIOT *f, int flags) { ___mkd_initmmiot(f, 0); f->flags = flags & USER_FLAGS; ___mkd_reparse(bfr, size, 0, f); ___mkd_emblock(f); }
/* reparse() into a cstring */ void Csreparse(Cstring *iot, char *buf, int size, int flags) { MMIOT f; ___mkd_initmmiot(&f, 0); ___mkd_reparse(buf, size, 0, &f, 0); ___mkd_emblock(&f); SUFFIX(*iot, T(f.out), S(f.out)); ___mkd_freemmiot(&f, 0); }
/* Smarty-pants-style chrome for quotes, -, ellipses, and (r)(c)(tm) */ static int smartypants(int c, int *flags, MMIOT *f) { int i; if ( f->flags & (DENY_SMARTY|INSIDE_TAG) ) return 0; for ( i=0; i < NRSMART; i++) if ( (c == smarties[i].c0) && islike(f, smarties[i].pat) ) { if ( smarties[i].entity ) Qprintf(f, "&%s;", smarties[i].entity); shift(f, smarties[i].shift); return 1; } switch (c) { case '<' : return 0; case '\'': if ( smartyquote(flags, 's', f) ) return 1; break; case '"': if ( smartyquote(flags, 'd', f) ) return 1; break; case '`': if ( peek(f, 1) == '`' ) { int j = 2; while ( (c=peek(f,j)) != EOF ) { if ( c == '\\' ) j += 2; else if ( c == '`' ) break; else if ( c == '\'' && peek(f, j+1) == '\'' ) { Qstring("“", f); ___mkd_reparse(cursor(f)+1, j-2, 0, f); Qstring("”", f); shift(f,j+1); return 1; } else ++j; } } break; } return 0; } /* smartypants */
static void text(MMIOT *f) { int c, j; int rep; int smartyflags = 0; while (1) { if ( (f->flags & AUTOLINK) && isalpha(peek(f,1)) ) maybe_autolink(f); c = pull(f); if (c == EOF) break; if ( smartypants(c, &smartyflags, f) ) continue; switch (c) { case 0: break; case 3: Qstring("<br/>", f); break; case '>': if ( tag_text(f) ) Qstring(">", f); else Qchar(c, f); break; case '"': if ( tag_text(f) ) Qstring(""", f); else Qchar(c, f); break; case '!': if ( peek(f,1) == '[' ) { pull(f); if ( tag_text(f) || !linkylinky(1, f) ) Qstring("![", f); } else Qchar(c, f); break; case '[': if ( tag_text(f) || !linkylinky(0, f) ) Qchar(c, f); break; #if SUPERSCRIPT /* A^B -> A<sup>B</sup> */ case '^': if ( (f->flags & (STRICT|INSIDE_TAG)) || isthisspace(f,-1) || isthisspace(f,1) ) Qchar(c,f); else { char *sup = cursor(f); int len = 0; Qstring("<sup>",f); while ( !isthisspace(f,1+len) ) { ++len; } shift(f,len); ___mkd_reparse(sup, len, 0, f); Qstring("</sup>", f); } break; #endif case '_': #if RELAXED_EMPHASIS /* Underscores don't count if they're in the middle of a word */ if ( !(f->flags & STRICT) && isthisalnum(f,-1) && isthisalnum(f,1) ) { Qchar(c, f); break; } #endif case '*': #if RELAXED_EMPHASIS /* Underscores & stars don't count if they're out in the middle * of whitespace */ if ( !(f->flags & STRICT) && isthisspace(f,-1) && isthisspace(f,1) ) { Qchar(c, f); break; } /* else fall into the regular old emphasis case */ #endif if ( tag_text(f) ) Qchar(c, f); else { for (rep = 1; peek(f,1) == c; pull(f) ) ++rep; Qem(f,c,rep); } break; case '`': if ( tag_text(f) || !iscodeblock(f) ) Qchar(c, f); else { Qstring("<code>", f); if ( peek(f, 1) == '`' ) { pull(f); code(2, f); } else code(1, f); Qstring("</code>", f); } break; case '\\': switch ( c = pull(f) ) { case '&': Qstring("&", f); break; case '<': Qstring("<", f); break; case '\\': case '>': case '#': case '.': case '-': case '+': case '{': case '}': case ']': case '(': case ')': case '"': case '\'': case '!': case '[': case '*': case '_': case '`': Qchar(c, f); break; default: Qchar('\\', f); if ( c != EOF ) shift(f,-1); break; } break; case '<': if ( !maybe_tag_or_link(f) ) Qstring("<", f); break; case '&': j = (peek(f,1) == '#' ) ? 2 : 1; while ( isthisalnum(f,j) ) ++j; if ( peek(f,j) != ';' ) Qstring("&", f); else Qchar(c, f); break; default: Qchar(c, f); break; } } /* truncate the input string after we've finished processing it */ S(f->in) = f->isp = 0; } /* text */
static void text(MMIOT *f) { int c, j; int rep; int smartyflags = 0; while (1) { if ( (f->flags & MKD_AUTOLINK) && isalpha(peek(f,1)) && !tag_text(f) ) maybe_autolink(f); c = pull(f); if (c == EOF) break; if ( smartypants(c, &smartyflags, f) ) continue; switch (c) { case 0: break; case 3: Qstring(tag_text(f) ? " " : "<br/>", f); break; case '>': if ( tag_text(f) ) Qstring(">", f); else Qchar(c, f); break; case '"': if ( tag_text(f) ) Qstring(""", f); else Qchar(c, f); break; case '!': if ( peek(f,1) == '[' ) { pull(f); if ( tag_text(f) || !linkylinky(1, f) ) Qstring("![", f); } else Qchar(c, f); break; case '[': if ( tag_text(f) || !linkylinky(0, f) ) Qchar(c, f); break; /* A^B -> A<sup>B</sup> */ case '^': if ( (f->flags & (MKD_NOSUPERSCRIPT|MKD_STRICT|MKD_TAGTEXT)) || isthisspace(f,-1) || isthisspace(f,1) ) Qchar(c,f); else { char *sup = cursor(f); int len = 0; if ( peek(f,1) == '(' ) { int here = mmiottell(f); pull(f); if ( (len = parenthetical('(',')',f)) <= 0 ) { mmiotseek(f,here); Qchar(c, f); break; } sup++; } else { while ( isthisalnum(f,1+len) ) ++len; if ( !len ) { Qchar(c,f); break; } shift(f,len); } Qstring("<sup>",f); ___mkd_reparse(sup, len, 0, f); Qstring("</sup>", f); } break; case '_': /* Underscores don't count if they're in the middle of a word */ if ( !(f->flags & (MKD_NORELAXED|MKD_STRICT)) && isthisalnum(f,-1) && isthisalnum(f,1) ) { Qchar(c, f); break; } case '*': /* Underscores & stars don't count if they're out in the middle * of whitespace */ if ( isthisspace(f,-1) && isthisspace(f,1) ) { Qchar(c, f); break; } /* else fall into the regular old emphasis case */ if ( tag_text(f) ) Qchar(c, f); else { for (rep = 1; peek(f,1) == c; pull(f) ) ++rep; Qem(f,c,rep); } break; case '~': if ( (f->flags & (MKD_NOSTRIKETHROUGH|MKD_TAGTEXT|MKD_STRICT)) || !tickhandler(f,c,2,delspan) ) Qchar(c, f); break; case '`': if ( tag_text(f) || !tickhandler(f,c,1,codespan) ) Qchar(c, f); break; case '\\': switch ( c = pull(f) ) { case '&': Qstring("&", f); break; case '<': Qstring("<", f); break; case '^': if ( f->flags & (MKD_STRICT|MKD_NOSUPERSCRIPT) ) { Qchar('\\', f); shift(f,-1); break; } Qchar(c, f); break; case '>': case '#': case '.': case '-': case '+': case '{': case '}': case ']': case '!': case '[': case '*': case '_': case '\\':case '(': case ')': case '`': Qchar(c, f); break; default: Qchar('\\', f); if ( c != EOF ) shift(f,-1); break; } break; case '<': if ( !maybe_tag_or_link(f) ) Qstring("<", f); break; case '&': j = (peek(f,1) == '#' ) ? 2 : 1; while ( isthisalnum(f,j) ) ++j; if ( peek(f,j) != ';' ) Qstring("&", f); else Qchar(c, f); break; default: Qchar(c, f); break; } } /* truncate the input string after we've finished processing it */ S(f->in) = f->isp = 0; } /* text */