ext/generate.c in pixeltrix-rdiscount-1.2.11 vs ext/generate.c in pixeltrix-rdiscount-1.3.4

- old
+ new

@@ -24,10 +24,11 @@ typedef int (*stfu)(const void*,const void*); /* forward declarations */ +static int iscodeblock(MMIOT*); static void code(int, MMIOT*); static void text(MMIOT *f); static Paragraph *display(Paragraph*, MMIOT*); /* externals from markdown.c */ @@ -72,10 +73,35 @@ { return T(f->in) + f->isp; } +static int +isthisspace(MMIOT *f, int i) +{ + int c = peek(f, i); + + return isspace(c) || (c == EOF); +} + + +static int +isthisalnum(MMIOT *f, int i) +{ + int c = peek(f, i); + + return (c != EOF) && isalnum(c); +} + + +static int +isthisnonword(MMIOT *f, int i) +{ + return isthisspace(f, i) || ispunct(peek(f,i)); +} + + /* return/set the current cursor position */ #define mmiotseek(f,x) (f->isp = x) #define mmiottell(f) (f->isp) @@ -249,14 +275,14 @@ start->b_count -= match; } } -/* emblock() +/* ___mkd_emblock() */ -static void -emblock(MMIOT *f) +void +___mkd_emblock(MMIOT *f) { int i; block *p; for (i=0; i < S(f->Q); i++) { @@ -273,12 +299,12 @@ } /* generate html from a markup fragment */ -static void -reparse(char *bfr, int size, int flags, MMIOT *f) +void +___mkd_reparse(char *bfr, int size, int flags, MMIOT *f) { MMIOT sub; ___mkd_initmmiot(&sub, f->footnotes); @@ -288,11 +314,11 @@ push(bfr, size, &sub); EXPAND(sub.in) = 0; S(sub.in)--; text(&sub); - emblock(&sub); + ___mkd_emblock(&sub); Qwrite(T(sub.out), S(sub.out), f); ___mkd_freemmiot(&sub, f->footnotes); } @@ -311,10 +337,12 @@ if ( c == '&' ) Qstring("&amp;", f); else if ( c == '<' ) Qstring("&lt;", f); + else if ( isalnum(c) || ispunct(c) ) + Qchar(c, f); else Qchar(c, f); } } @@ -467,16 +495,18 @@ static int linkykey(int image, Footnote *val, MMIOT *f) { Footnote *ret; Cstring mylabel; + int here; memset(val, 0, sizeof *val); if ( (T(val->tag) = linkylabel(f, &S(val->tag))) == 0 ) return 0; + here = mmiottell(f); eatspace(f); switch ( pull(f) ) { case '(': /* embedded link */ if ( (T(val->link) = linkyurl(f,&S(val->link))) == 0 ) @@ -487,18 +517,25 @@ T(val->title) = linkytitle(f, &S(val->title)); return peek(f,0) == ')'; - case '[': + case '[': /* footnote links /as defined in the standard/ */ + default: /* footnote links -- undocumented extension */ /* footnote link */ mylabel = val->tag; - if ( (T(val->tag) = linkylabel(f, &S(val->tag))) == 0 ) - return 0; + if ( peek(f,0) == '[' ) { + if ( (T(val->tag) = linkylabel(f, &S(val->tag))) == 0 ) + return 0; - if ( !S(val->tag) ) - val->tag = mylabel; + if ( !S(val->tag) ) + val->tag = mylabel; + } + else if ( f->flags & MKD_1_COMPAT ) + break; + else + mmiotseek(f,here); ret = bsearch(val, T(*f->footnotes), S(*f->footnotes), sizeof *val, (stfu)__mkd_footsort); if ( ret ) { @@ -574,11 +611,11 @@ { int start = mmiottell(f); Footnote link; linkytype *tag; - if ( !(linkykey(image, &link, f) && S(link.tag)) ) { + if ( !linkykey(image, &link, f) ) { mmiotseek(f, start); return 0; } if ( image ) @@ -603,16 +640,16 @@ Qprintf(f, " width=\"%d\"", link.width); } if ( S(link.title) ) { Qstring(" title=\"", f); - reparse(T(link.title), S(link.title), INSIDE_TAG, f); + ___mkd_reparse(T(link.title), S(link.title), INSIDE_TAG, f); Qchar('"', f); } Qstring(tag->text_pfx, f); - reparse(T(link.tag), S(link.tag), tag->flags, f); + ___mkd_reparse(T(link.tag), S(link.tag), tag->flags, f); Qstring(tag->text_sfx, f); } else Qwrite(T(link.link) + tag->szpat, S(link.link) - tag->szpat, f); @@ -657,15 +694,15 @@ int c = toupper(peek(f, 1)); if ( f->flags & DENY_HTML ) return 1; - if ( c == 'A' && (f->flags & DENY_A) && !isalnum(peek(f,2)) ) + if ( c == 'A' && (f->flags & DENY_A) && !isthisalnum(f,2) ) return 1; if ( c == 'I' && (f->flags & DENY_IMG) && strncasecmp(cursor(f)+1, "MG", 2) == 0 - && !isalnum(peek(f,4)) ) + && !isthisalnum(f,4) ) return 1; return 0; } @@ -741,26 +778,10 @@ shift(f, -(size+1)); return 0; } /* maybe_tag_or_link */ -static int -isthisspace(MMIOT *f, int i) -{ - int c = peek(f, i); - - return isspace(c) || (c == EOF); -} - - -static int -isthisnonword(MMIOT *f, int i) -{ - return isthisspace(f, i) || ispunct(peek(f,i)); -} - - /* smartyquote code that's common for single and double quotes */ static int smartyquote(int *flags, char typeofquote, MMIOT *f) { @@ -871,11 +892,11 @@ j += 2; else if ( c == '`' ) break; else if ( c == '\'' && peek(f, j+1) == '\'' ) { Qstring("&ldquo;", f); - reparse(cursor(f)+1, j-2, 0, f); + ___mkd_reparse(cursor(f)+1, j-2, 0, f); Qstring("&rdquo;", f); shift(f,j+1); return 1; } else ++j; @@ -926,32 +947,32 @@ break; case '[': if ( tag_text(f) || !linkylinky(0, f) ) Qchar(c, f); break; #if SUPERSCRIPT - case '^': if ( isthisspace(f,-1) || isthisspace(f,1) ) + /* 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); - reparse(sup, len, 0, f); + ___mkd_reparse(sup, len, 0, f); Qstring("</sup>", f); } break; #endif case '_': #if RELAXED_EMPHASIS - /* If RELAXED_EMPHASIS, underscores don't count when - * they're in the middle of a word. - */ - if ( (isthisspace(f,-1) && isthisspace(f,1)) - || (isalnum(peek(f,-1)) && isalnum(peek(f,1))) ) { + /* Underscores don't count if they're in the middle of a word */ + if ( (!(f->flags & STRICT)) + && ((isthisspace(f,-1) && isthisspace(f,1)) + || (isthisalnum(f,-1) && isthisalnum(f,1))) ){ Qchar(c, f); break; } /* else fall into the regular old emphasis case */ #endif @@ -962,11 +983,11 @@ ++rep; Qem(f,c,rep); } break; - case '`': if ( tag_text(f) ) + case '`': if ( tag_text(f) || !iscodeblock(f) ) Qchar(c, f); else { Qstring("<code>", f); if ( peek(f, 1) == '`' ) { pull(f); @@ -1001,11 +1022,11 @@ case '<': if ( !maybe_tag_or_link(f) ) Qstring("&lt;", f); break; case '&': j = (peek(f,1) == '#' ) ? 2 : 1; - while ( isalnum(peek(f,j)) ) + while ( isthisalnum(f,j) ) ++j; if ( peek(f,j) != ';' ) Qstring("&amp;", f); else @@ -1014,14 +1035,36 @@ default: Qchar(c, f); break; } } + /* truncate the input string after we've finished processing it */ + S(f->in) = f->isp = 0; } /* text */ static int +iscodeblock(MMIOT *f) +{ + int i=1, single = 1, c; + + if ( peek(f,i) == '`' ) { + single=0; + i++; + } + while ( (c=peek(f,i)) != EOF ) { + if ( (c == '`') && (single || peek(f,i+1) == '`') ) + return 1; + else if ( c == '\\' ) + i++; + i++; + } + return 0; + +} + +static int endofcode(int escape, int offset, MMIOT *f) { switch (escape) { case 2: if ( peek(f, offset+1) == '`' ) { shift(f,1); @@ -1070,11 +1113,17 @@ /* print a header block */ static void printheader(Paragraph *pp, MMIOT *f) { - Qprintf(f, "<h%d>", pp->hnumber); + Qprintf(f, "<h%d", pp->hnumber); + if ( f->flags & TOC ) { + Qprintf(f, " id=\"", pp->hnumber); + mkd_string_to_anchor(T(pp->text->text), S(pp->text->text), Qchar, f); + Qchar('"', f); + } + Qchar('>', f); push(T(pp->text->text), S(pp->text->text), f); text(f); Qprintf(f, "</h%d>", pp->hnumber); } @@ -1092,10 +1141,11 @@ && T(t->text)[S(t->text)-1] == ' ') { push(T(t->text), S(t->text)-2, f); push("<br/>\n", 6, f); } else { + ___mkd_tidy(t); push(T(t->text), S(t->text), f); if ( t->next ) push("\n", 1, f); } } @@ -1147,23 +1197,25 @@ blanks++; } static void -htmlify(Paragraph *p, char *block, MMIOT *f) +htmlify(Paragraph *p, char *block, char *arguments, MMIOT *f) { - emblock(f); - if ( block ) Qprintf(f, "<%s>", block); - emblock(f); + ___mkd_emblock(f); + if ( block ) + Qprintf(f, arguments ? "<%s %s>" : "<%s>", block, arguments); + ___mkd_emblock(f); while (( p = display(p, f) )) { - emblock(f); + ___mkd_emblock(f); Qstring("\n\n", f); } - if ( block ) Qprintf(f, "</%s>", block); - emblock(f); + if ( block ) + Qprintf(f, "</%s>", block); + ___mkd_emblock(f); } #if DL_TAG_EXTENSION static void @@ -1175,15 +1227,15 @@ Qstring("<dl>\n", f); for ( ; p ; p = p->next) { for ( tag = p->text; tag; tag = tag->next ) { Qstring("<dt>", f); - reparse(T(tag->text), S(tag->text), 0, f); + ___mkd_reparse(T(tag->text), S(tag->text), 0, f); Qstring("</dt>\n", f); } - htmlify(p->down, "dd", f); + htmlify(p->down, "dd", p->ident, f); } Qstring("</dl>", f); } } @@ -1192,14 +1244,17 @@ static void listdisplay(int typ, Paragraph *p, MMIOT* f) { if ( p ) { - Qprintf(f, "<%cl>\n", (typ==UL)?'u':'o'); + Qprintf(f, "<%cl", (typ==UL)?'u':'o'); + if ( typ == AL ) + Qprintf(f, " type=a"); + Qprintf(f, ">\n"); for ( ; p ; p = p->next ) { - htmlify(p->down, "li", f); + htmlify(p->down, "li", p->ident, f); Qchar('\n', f); } Qprintf(f, "</%cl>\n", (typ==UL)?'u':'o'); } @@ -1225,15 +1280,16 @@ case CODE: printcode(p->text, f); break; case QUOTE: - htmlify(p->down, "blockquote", f); + htmlify(p->down, p->ident ? "div" : "blockquote", p->ident, f); break; case UL: case OL: + case AL: listdisplay(p->typ, p->down, f); break; #if DL_TAG_EXTENSION case DL: @@ -1286,32 +1342,32 @@ int mkd_document(Document *p, char **res) { if ( p && p->compiled ) { if ( ! p->html ) { - htmlify(p->code, 0, p->ctx); + htmlify(p->code, 0, 0, p->ctx); p->html = 1; } *res = T(p->ctx->out); return S(p->ctx->out); } return EOF; } -/* public interface for reparse() +/* public interface for ___mkd_reparse() */ int mkd_text(char *bfr, int size, FILE *output, int flags) { MMIOT f; ___mkd_initmmiot(&f, 0); f.flags = flags & USER_FLAGS; - reparse(bfr, size, 0, &f); - emblock(&f); + ___mkd_reparse(bfr, size, 0, &f); + ___mkd_emblock(&f); if ( flags & CDATA_OUTPUT ) ___mkd_xml(T(f.out), S(f.out), output); else fwrite(T(f.out), S(f.out), 1, output);