static Line * definition_block(Paragraph *top, int clip, MMIOT *f, int kind) { ParagraphRoot d = { 0, 0 }; Paragraph *p; Line *q = top->text, *text = 0, *labels; int z, para; while (( labels = q )) { if ( (q = isdefinition(labels, &z, &kind)) == 0 ) break; if ( (text = skipempty(q->next)) == 0 ) break; if (( para = (text != q->next) )) ___mkd_freeLineRange(q, text); q->next = 0; if ( kind == 1 /* discount dl */ ) for ( q = labels; q; q = q->next ) { CLIP(q->text, 0, 1); UNCHECK(q); S(q->text)--; } dd_block: p = Pp(&d, text, LISTITEM); text = listitem(p, clip, f->flags, (kind==2) ? is_extra_dd : 0); p->down = compile(p->text, 0, f); p->text = labels; labels = 0; if ( para && p->down ) p->down->align = PARA; if ( (q = skipempty(text)) == 0 ) break; if (( para = (q != text) )) { Line anchor; anchor.next = text; ___mkd_freeLineRange(&anchor,q); text = q; } if ( kind == 2 && is_extra_dd(q) ) goto dd_block; } top->text = 0; top->down = T(d); return text; }
static Line * enumerated_block(Paragraph *top, int clip, MMIOT *f, int list_class) { ParagraphRoot d = { 0, 0 }; Paragraph *p; Line *q = top->text, *text; int para = 0, z; while (( text = q )) { p = Pp(&d, text, LISTITEM); text = listitem(p, clip, f->flags, 0); p->down = compile(p->text, 0, f); p->text = 0; if ( para && p->down ) p->down->align = PARA; if ( (q = skipempty(text)) == 0 || islist(q, &clip, f->flags, &z) != list_class ) break; if ( para = (q != text) ) { Line anchor; anchor.next = text; ___mkd_freeLineRange(&anchor, q); if ( p->down ) p->down->align = PARA; } } top->text = 0; top->down = T(d); return text; }
/* * pull in a list block. A list block starts with a list marker and * runs until the next list marker, the next non-indented paragraph, * or EOF. You do not have to indent nonblank lines after the list * marker, but multiple paragraphs need to start with a 4-space indent. */ static Line * listitem(Paragraph *p, int indent, DWORD flags, linefn check) { Line *t, *q; int clip = indent; int z; for ( t = p->text; t ; t = q) { CLIP(t->text, 0, clip); UNCHECK(t); t->dle = mkd_firstnonblank(t); /* even though we had to trim a long leader off this item, * the indent for trailing paragraphs is still 4... */ if (indent > 4) { indent = 4; } if ( (q = skipempty(t->next)) == 0 ) { ___mkd_freeLineRange(t,q); return 0; } /* after a blank line, the next block needs to start with a line * that's indented 4(? -- reference implementation allows a 1 * character indent, but that has unfortunate side effects here) * spaces, but after that the line doesn't need any indentation */ if ( q != t->next ) { if (q->dle < indent) { q = t->next; t->next = 0; return q; } /* indent at least 2, and at most as * as far as the initial line was indented. */ indent = clip ? clip : 2; } if ( (q->dle < indent) && (ishr(q) || islist(q,&z,flags,&z) || (check && (*check)(q))) && !issetext(q,&z) ) { q = t->next; t->next = 0; return q; } clip = (q->dle > indent) ? indent : q->dle; } return t; }
/* * accumulate a blockquote. * * one sick horrible thing about blockquotes is that even though * it just takes ^> to start a quote, following lines, if quoted, * assume that the prefix is ``> ''. This means that code needs * to be indented *5* spaces from the leading '>', but *4* spaces * from the start of the line. This does not appear to be * documented in the reference implementation, but it's the * way the markdown sample web form at Daring Fireball works. */ static Line * quoteblock(Paragraph *p, DWORD flags) { Line *t, *q; int qp; for ( t = p->text; t ; t = q ) { if ( isquote(t) ) { /* clip leading spaces */ for (qp = 0; T(t->text)[qp] != '>'; qp ++) /* assert: the first nonblank character on this line * will be a > */; /* clip '>' */ qp++; /* clip next space, if any */ if ( T(t->text)[qp] == ' ' ) qp++; CLIP(t->text, 0, qp); UNCHECK(t); t->dle = mkd_firstnonblank(t); } q = skipempty(t->next); if ( (q == 0) || ((q != t->next) && (!isquote(q) || isdivmarker(q,1,flags))) ) { ___mkd_freeLineRange(t, q); t = q; break; } } if ( isdivmarker(p->text,0,flags) ) { char *prefix = "class"; int i; q = p->text; p->text = p->text->next; if ( (i = szmarkerclass(1+T(q->text))) == 3 ) /* and this would be an "%id:" prefix */ prefix="id"; if ( p->ident = malloc(4+strlen(prefix)+S(q->text)) ) sprintf(p->ident, "%s=\"%.*s\"", prefix, S(q->text)-(i+2), T(q->text)+(i+1) ); ___mkd_freeLine(q); } return t; }
static Line * codeblock(Paragraph *p) { Line *t = p->text, *r; for ( ; t; t = r ) { CLIP(t->text,0,4); t->dle = mkd_firstnonblank(t); if ( !( (r = skipempty(t->next)) && iscode(r)) ) { ___mkd_freeLineRange(t,r); t->next = 0; return r; } } return t; }
static Line* is_extra_dt(Line *t, int *clip, DWORD flags) { if ( flags & MKD_DLEXTRA && t && t->next && S(t->text) && T(t->text)[0] != '=' && T(t->text)[S(t->text)-1] != '=') { Line *x; if ( iscode(t) || end_of_block(t, flags) ) return 0; if ( (x = skipempty(t->next)) && is_extra_dd(x) ) { *clip = x->dle+2; return t; } if ( x=is_extra_dt(t->next, clip, flags) ) return x; } return 0; }
static Line* is_extra_dt(Line *t, int *clip) { #if USE_EXTRA_DL if ( t && t->next && S(t->text) && T(t->text)[0] != '=' && T(t->text)[S(t->text)-1] != '=') { Line *x; if ( iscode(t) || end_of_block(t) ) return 0; if ( (x = skipempty(t->next)) && is_extra_dd(x) ) { *clip = x->dle+2; return t; } if ( x=is_extra_dt(t->next, clip) ) return x; } #endif return 0; }