markdown.c (discount-2.2.4.tar.bz2) | : | markdown.c (discount-2.2.6.tar.bz2) | ||
---|---|---|---|---|
skipping to change at line 181 | skipping to change at line 181 | |||
#define UNLESS_FENCED(t) if (fenced) { \ | #define UNLESS_FENCED(t) if (fenced) { \ | |||
other = 1; l->count += (c == ' ' ? 0 : -1); \ | other = 1; l->count += (c == ' ' ? 0 : -1); \ | |||
} else { t; } | } else { t; } | |||
/* | /* | |||
* walk a line, seeing if it's any of half a dozen interesting regular | * walk a line, seeing if it's any of half a dozen interesting regular | |||
* types. | * types. | |||
*/ | */ | |||
static void | static void | |||
checkline(Line *l, DWORD flags) | checkline(Line *l, mkd_flag_t flags) | |||
{ | { | |||
int eol, i; | int eol, i; | |||
int dashes = 0, spaces = 0, | int dashes = 0, spaces = 0, | |||
equals = 0, underscores = 0, | equals = 0, underscores = 0, | |||
stars = 0, tildes = 0, other = 0, | stars = 0, tildes = 0, other = 0, | |||
backticks = 0, fenced = 0; | backticks = 0, fenced = 0; | |||
l->flags |= CHECKED; | l->flags |= CHECKED; | |||
l->kind = chk_text; | l->kind = chk_text; | |||
l->count = 0; | l->count = 0; | |||
skipping to change at line 211 | skipping to change at line 211 | |||
if ( c != ' ' ) l->count++; | if ( c != ' ' ) l->count++; | |||
switch (c) { | switch (c) { | |||
case '-': UNLESS_FENCED(dashes = 1); break; | case '-': UNLESS_FENCED(dashes = 1); break; | |||
case ' ': UNLESS_FENCED(spaces = 1); break; | case ' ': UNLESS_FENCED(spaces = 1); break; | |||
case '=': equals = 1; break; | case '=': equals = 1; break; | |||
case '_': UNLESS_FENCED(underscores = 1); break; | case '_': UNLESS_FENCED(underscores = 1); break; | |||
case '*': stars = 1; break; | case '*': stars = 1; break; | |||
default: | default: | |||
if (flags & MKD_FENCEDCODE) { | if ( is_flag_set(flags, MKD_FENCEDCODE) ) { | |||
switch (c) { | switch (c) { | |||
case '~': if (other) return; is_fence_char = 1; tildes = 1; brea k; | case '~': if (other) return; is_fence_char = 1; tildes = 1; brea k; | |||
case '`': if (other) return; is_fence_char = 1; backticks = 1; b reak; | case '`': if (other) return; is_fence_char = 1; backticks = 1; b reak; | |||
} | } | |||
if (is_fence_char) { | if (is_fence_char) { | |||
fenced = 1; | fenced = 1; | |||
break; | break; | |||
} | } | |||
} | } | |||
other = 1; | other = 1; | |||
skipping to change at line 366 | skipping to change at line 366 | |||
return (t->dle < 4 && T(t->text)[t->dle] == '>'); | return (t->dle < 4 && T(t->text)[t->dle] == '>'); | |||
} | } | |||
static inline int | static inline int | |||
iscode(Line *t) | iscode(Line *t) | |||
{ | { | |||
return (t->dle >= 4); | return (t->dle >= 4); | |||
} | } | |||
static inline int | static inline int | |||
ishr(Line *t, DWORD flags) | ishr(Line *t, mkd_flag_t flags) | |||
{ | { | |||
if ( ! (t->flags & CHECKED) ) | if ( ! (t->flags & CHECKED) ) | |||
checkline(t, flags); | checkline(t, flags); | |||
if ( t->count > 2 ) | if ( t->count > 2 ) | |||
return t->kind == chk_hr || t->kind == chk_dash || t->kind == chk_equal; | return t->kind == chk_hr || t->kind == chk_dash || t->kind == chk_equal; | |||
return 0; | return 0; | |||
} | } | |||
static int | static int | |||
issetext(Line *t, int *htyp, DWORD flags) | issetext(Line *t, int *htyp, mkd_flag_t flags) | |||
{ | { | |||
Line *n; | Line *n; | |||
/* check for setext-style HEADER | /* check for setext-style HEADER | |||
* ====== | * ====== | |||
*/ | */ | |||
if ( (n = t->next) ) { | if ( (n = t->next) ) { | |||
if ( !(n->flags & CHECKED) ) | if ( !(n->flags & CHECKED) ) | |||
checkline(n, flags); | checkline(n, flags); | |||
if ( n->kind == chk_dash || n->kind == chk_equal ) { | if ( n->kind == chk_dash || n->kind == chk_equal ) { | |||
*htyp = SETEXT; | *htyp = SETEXT; | |||
return 1; | return 1; | |||
} | } | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
static int | static int | |||
ishdr(Line *t, int *htyp, DWORD flags) | ishdr(Line *t, int *htyp, mkd_flag_t flags) | |||
{ | { | |||
/* ANY leading `#`'s make this into an ETX header | /* ANY leading `#`'s make this into an ETX header | |||
*/ | */ | |||
if ( (t->dle == 0) && (S(t->text) > 1) && (T(t->text)[0] == '#') ) { | if ( (t->dle == 0) && (S(t->text) > 1) && (T(t->text)[0] == '#') ) { | |||
*htyp = ETX; | *htyp = ETX; | |||
return 1; | return 1; | |||
} | } | |||
/* And if not, maybe it's a SETEXT header instead | /* And if not, maybe it's a SETEXT header instead | |||
*/ | */ | |||
return issetext(t, htyp, flags); | return issetext(t, htyp, flags); | |||
} | } | |||
static inline int | static inline int | |||
end_of_block(Line *t, DWORD flags) | end_of_block(Line *t, mkd_flag_t flags) | |||
{ | { | |||
int dummy; | int dummy; | |||
if ( !t ) | if ( !t ) | |||
return 0; | return 0; | |||
return ( (S(t->text) <= t->dle) || ishr(t, flags) || ishdr(t, &dummy, flags) ); | return ( (S(t->text) <= t->dle) || ishr(t, flags) || ishdr(t, &dummy, flags) ); | |||
} | } | |||
static Line* | static Line* | |||
is_discount_dt(Line *t, int *clip, DWORD flags) | is_discount_dt(Line *t, int *clip, mkd_flag_t flags) | |||
{ | { | |||
if ( !(flags & MKD_NODLDISCOUNT) | if ( !is_flag_set(flags, MKD_NODLDISCOUNT) | |||
&& t | && t | |||
&& t->next | && t->next | |||
&& (S(t->text) > 2) | && (S(t->text) > 2) | |||
&& (t->dle == 0) | && (t->dle == 0) | |||
&& (T(t->text)[0] == '=') | && (T(t->text)[0] == '=') | |||
&& (T(t->text)[S(t->text)-1] == '=') ) { | && (T(t->text)[S(t->text)-1] == '=') ) { | |||
if ( t->next->dle >= 4 ) { | if ( t->next->dle >= 4 ) { | |||
*clip = 4; | *clip = 4; | |||
return t; | return t; | |||
} | } | |||
skipping to change at line 451 | skipping to change at line 451 | |||
} | } | |||
static int | static int | |||
is_extra_dd(Line *t) | is_extra_dd(Line *t) | |||
{ | { | |||
return (t->dle < 4) && (T(t->text)[t->dle] == ':') | return (t->dle < 4) && (T(t->text)[t->dle] == ':') | |||
&& isspace(T(t->text)[t->dle+1]); | && isspace(T(t->text)[t->dle+1]); | |||
} | } | |||
static Line* | static Line* | |||
is_extra_dt(Line *t, int *clip, DWORD flags) | is_extra_dt(Line *t, int *clip, mkd_flag_t flags) | |||
{ | { | |||
if ( flags & MKD_DLEXTRA | if ( is_flag_set(flags, MKD_DLEXTRA) | |||
&& t | && t | |||
&& t->next && S(t->text) && T(t->text)[0] != '=' | && t->next && S(t->text) && T(t->text)[0] != '=' | |||
&& T(t->text)[S(t->text)-1] != '=') { | && T(t->text)[S(t->text)-1] != '=') { | |||
Line *x; | Line *x; | |||
if ( iscode(t) || end_of_block(t, flags) ) | if ( iscode(t) || end_of_block(t, flags) ) | |||
return 0; | return 0; | |||
if ( (x = skipempty(t->next)) && is_extra_dd(x) ) { | if ( (x = skipempty(t->next)) && is_extra_dd(x) ) { | |||
*clip = x->dle+2; | *clip = x->dle+2; | |||
return t; | return t; | |||
} | } | |||
if ( x=is_extra_dt(t->next, clip, flags) ) | if ( x=is_extra_dt(t->next, clip, flags) ) | |||
return x; | return x; | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
static Line* | static Line* | |||
isdefinition(Line *t, int *clip, int *kind, DWORD flags) | isdefinition(Line *t, int *clip, int *kind, mkd_flag_t flags) | |||
{ | { | |||
Line *ret; | Line *ret; | |||
*kind = 1; | *kind = 1; | |||
if ( ret = is_discount_dt(t,clip,flags) ) | if ( ret = is_discount_dt(t,clip,flags) ) | |||
return ret; | return ret; | |||
*kind=2; | *kind=2; | |||
return is_extra_dt(t,clip,flags); | return is_extra_dt(t,clip,flags); | |||
} | } | |||
static int | static int | |||
islist(Line *t, int *clip, DWORD flags, int *list_type) | islist(Line *t, int *clip, mkd_flag_t flags, int *list_type) | |||
{ | { | |||
int i, j; | int i, j; | |||
char *q; | char *q; | |||
if ( end_of_block(t, flags) ) | if ( end_of_block(t, flags) ) | |||
return 0; | return 0; | |||
if ( !(flags & (MKD_NODLIST|MKD_STRICT)) && isdefinition(t,clip,list_type,fl | if ( !(is_flag_set(flags, MKD_NODLIST) || is_flag_set(flags, MKD_STRICT)) | |||
ags) ) | && isdefinition(t,clip,list_type,flags) ) | |||
return DL; | return DL; | |||
if ( strchr("*-+", T(t->text)[t->dle]) && isspace(T(t->text)[t->dle+1]) ) { | if ( strchr("*-+", T(t->text)[t->dle]) && isspace(T(t->text)[t->dle+1]) ) { | |||
i = nextnonblank(t, t->dle+1); | i = nextnonblank(t, t->dle+1); | |||
*clip = (i > 4) ? 4 : i; | *clip = (i > 4) ? 4 : i; | |||
*list_type = UL; | *list_type = UL; | |||
return (flags & MKD_EXPLICITLIST) ? UL : AL; | return is_flag_set(flags, MKD_EXPLICITLIST) ? UL : AL; | |||
} | } | |||
if ( (j = nextblank(t,t->dle)) > t->dle ) { | if ( (j = nextblank(t,t->dle)) > t->dle ) { | |||
if ( T(t->text)[j-1] == '.' ) { | if ( T(t->text)[j-1] == '.' ) { | |||
if ( !(flags & (MKD_NOALPHALIST|MKD_STRICT)) | if ( !(is_flag_set(flags, MKD_NOALPHALIST) || is_flag_set(flags, MKD_ | |||
&& (j == t->dle + 2) | STRICT)) | |||
&& (j == t->dle + 2) | ||||
&& isalpha(T(t->text)[t->dle]) ) { | && isalpha(T(t->text)[t->dle]) ) { | |||
j = nextnonblank(t,j); | j = nextnonblank(t,j); | |||
*clip = (j > 4) ? 4 : j; | *clip = (j > 4) ? 4 : j; | |||
*list_type = AL; | *list_type = AL; | |||
return AL; | return AL; | |||
} | } | |||
strtoul(T(t->text)+t->dle, &q, 10); | strtoul(T(t->text)+t->dle, &q, 10); | |||
if ( (q > T(t->text)+t->dle) && (q == T(t->text) + (j-1)) ) { | if ( (q > T(t->text)+t->dle) && (q == T(t->text) + (j-1)) ) { | |||
j = nextnonblank(t,j); | j = nextnonblank(t,j); | |||
skipping to change at line 597 | skipping to change at line 598 | |||
if ( !( (r = skipempty(t->next)) && iscode(r)) ) { | if ( !( (r = skipempty(t->next)) && iscode(r)) ) { | |||
___mkd_freeLineRange(t,r); | ___mkd_freeLineRange(t,r); | |||
t->next = 0; | t->next = 0; | |||
return r; | return r; | |||
} | } | |||
} | } | |||
return t; | return t; | |||
} | } | |||
static int | static int | |||
iscodefence(Line *r, int size, line_type kind, DWORD flags) | iscodefence(Line *r, int size, line_type kind, mkd_flag_t flags) | |||
{ | { | |||
if ( !(flags & MKD_FENCEDCODE) ) | if ( !is_flag_set(flags, MKD_FENCEDCODE) ) | |||
return 0; | return 0; | |||
if ( !(r->flags & CHECKED) ) | if ( !(r->flags & CHECKED) ) | |||
checkline(r, flags); | checkline(r, flags); | |||
if ( kind ) | if ( kind ) | |||
return (r->kind == kind) && (r->count >= size); | return (r->kind == kind) && (r->count >= size); | |||
else | else | |||
return (r->kind == chk_tilde || r->kind == chk_backtick) && (r->count >= size); | return (r->kind == chk_tilde || r->kind == chk_backtick) && (r->count >= size); | |||
} | } | |||
static Paragraph * | static Paragraph * | |||
fencedcodeblock(ParagraphRoot *d, Line **ptr, DWORD flags) | fencedcodeblock(ParagraphRoot *d, Line **ptr, mkd_flag_t flags) | |||
{ | { | |||
Line *first, *r; | Line *first, *r; | |||
Paragraph *ret; | Paragraph *ret; | |||
first = (*ptr); | first = (*ptr); | |||
/* don't allow zero-length code fences | /* don't allow zero-length code fences | |||
*/ | */ | |||
if ( (first->next == 0) || iscodefence(first->next, first->count, 0, flags) ) | if ( (first->next == 0) || iscodefence(first->next, first->count, 0, flags) ) | |||
return 0; | return 0; | |||
skipping to change at line 665 | skipping to change at line 666 | |||
&& (strncmp(T(last->text)+len-2, "<-", 2) == 0) ) { | && (strncmp(T(last->text)+len-2, "<-", 2) == 0) ) { | |||
CLIP(first->text, 0, 2); | CLIP(first->text, 0, 2); | |||
S(last->text) -= 2; | S(last->text) -= 2; | |||
return CENTER; | return CENTER; | |||
} | } | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
static int | static int | |||
endoftextblock(Line *t, int toplevelblock, DWORD flags) | endoftextblock(Line *t, int toplevelblock, mkd_flag_t flags) | |||
{ | { | |||
int z; | int z; | |||
if ( end_of_block(t, flags) || isquote(t) ) | if ( end_of_block(t, flags) || isquote(t) ) | |||
return 1; | return 1; | |||
/* HORRIBLE STANDARDS KLUDGES: | /* HORRIBLE STANDARDS KLUDGES: | |||
* 1. non-toplevel paragraphs absorb adjacent code blocks | * 1. non-toplevel paragraphs absorb adjacent code blocks | |||
* 2. Toplevel paragraphs eat absorb adjacent list items, | * 2. Toplevel paragraphs eat absorb adjacent list items, | |||
* but sublevel blocks behave properly. | * but sublevel blocks behave properly. | |||
* (What this means is that we only need to check for code | * (What this means is that we only need to check for code | |||
* blocks at toplevel, and only check for list items at | * blocks at toplevel, and only check for list items at | |||
* nested levels.) | * nested levels.) | |||
*/ | */ | |||
return toplevelblock ? 0 : islist(t,&z,flags,&z); | return toplevelblock ? 0 : islist(t,&z,flags,&z); | |||
} | } | |||
static Line * | static Line * | |||
textblock(Paragraph *p, int toplevel, DWORD flags) | textblock(Paragraph *p, int toplevel, mkd_flag_t flags) | |||
{ | { | |||
Line *t, *next; | Line *t, *next; | |||
for ( t = p->text; t ; t = next ) { | for ( t = p->text; t ; t = next ) { | |||
if ( ((next = t->next) == 0) || endoftextblock(next, toplevel, flags) ) { | if ( ((next = t->next) == 0) || endoftextblock(next, toplevel, flags) ) { | |||
p->align = centered(p->text, t); | p->align = centered(p->text, t); | |||
t->next = 0; | t->next = 0; | |||
return next; | return next; | |||
} | } | |||
} | } | |||
skipping to change at line 717 | skipping to change at line 718 | |||
return 0; | return 0; | |||
} | } | |||
/* | /* | |||
* check if the first line of a quoted block is the special div-not-quote | * check if the first line of a quoted block is the special div-not-quote | |||
* marker %[kind:]name% | * marker %[kind:]name% | |||
*/ | */ | |||
#define iscsschar(c) (isalpha(c) || (c == '-') || (c == '_') ) | #define iscsschar(c) (isalpha(c) || (c == '-') || (c == '_') ) | |||
static int | static int | |||
isdivmarker(Line *p, int start, DWORD flags) | isdivmarker(Line *p, int start, mkd_flag_t flags) | |||
{ | { | |||
char *s; | char *s; | |||
int last, i; | int last, i; | |||
if ( flags & (MKD_NODIVQUOTE|MKD_STRICT) ) | if ( is_flag_set(flags, MKD_NODIVQUOTE) || is_flag_set(flags, MKD_STRICT) ) | |||
return 0; | return 0; | |||
start = nextnonblank(p, start); | start = nextnonblank(p, start); | |||
last= S(p->text) - (1 + start); | last= S(p->text) - (1 + start); | |||
s = T(p->text) + start; | s = T(p->text) + start; | |||
if ( (last <= 0) || (*s != '%') || (s[last] != '%') ) | if ( (last <= 0) || (*s != '%') || (s[last] != '%') ) | |||
return 0; | return 0; | |||
i = szmarkerclass(s+1); | i = szmarkerclass(s+1); | |||
skipping to change at line 755 | skipping to change at line 756 | |||
* | * | |||
* one sick horrible thing about blockquotes is that even though | * one sick horrible thing about blockquotes is that even though | |||
* it just takes ^> to start a quote, following lines, if quoted, | * it just takes ^> to start a quote, following lines, if quoted, | |||
* assume that the prefix is ``> ''. This means that code needs | * assume that the prefix is ``> ''. This means that code needs | |||
* to be indented *5* spaces from the leading '>', but *4* spaces | * to be indented *5* spaces from the leading '>', but *4* spaces | |||
* from the start of the line. This does not appear to be | * from the start of the line. This does not appear to be | |||
* documented in the reference implementation, but it's the | * documented in the reference implementation, but it's the | |||
* way the markdown sample web form at Daring Fireball works. | * way the markdown sample web form at Daring Fireball works. | |||
*/ | */ | |||
static Line * | static Line * | |||
quoteblock(Paragraph *p, DWORD flags) | quoteblock(Paragraph *p, mkd_flag_t flags) | |||
{ | { | |||
Line *t, *q; | Line *t, *q; | |||
int qp; | int qp; | |||
for ( t = p->text; t ; t = q ) { | for ( t = p->text; t ; t = q ) { | |||
if ( isquote(t) ) { | if ( isquote(t) ) { | |||
/* clip leading spaces */ | /* clip leading spaces */ | |||
for (qp = 0; T(t->text)[qp] != '>'; qp ++) | for (qp = 0; T(t->text)[qp] != '>'; qp ++) | |||
/* assert: the first nonblank character on this line | /* assert: the first nonblank character on this line | |||
* will be a > | * will be a > | |||
skipping to change at line 813 | skipping to change at line 814 | |||
typedef int (*linefn)(Line *); | typedef int (*linefn)(Line *); | |||
/* | /* | |||
* pull in a list block. A list block starts with a list marker and | * 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, | * runs until the next list marker, the next non-indented paragraph, | |||
* or EOF. You do not have to indent nonblank lines after the list | * 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. | * marker, but multiple paragraphs need to start with a 4-space indent. | |||
*/ | */ | |||
static Line * | static Line * | |||
listitem(Paragraph *p, int indent, DWORD flags, linefn check) | listitem(Paragraph *p, int indent, mkd_flag_t flags, linefn check) | |||
{ | { | |||
Line *t, *q; | Line *t, *q; | |||
int clip = indent; | int clip = indent; | |||
int z; | int z; | |||
#ifdef GITHUB_CHECKBOX | #ifdef GITHUB_CHECKBOX | |||
int firstpara = 1; | int firstpara = 1; | |||
int ischeck; | int ischeck; | |||
#define CHECK_NOT 0 | #define CHECK_NOT 0 | |||
#define CHECK_NO 1 | #define CHECK_NO 1 | |||
#define CHECK_YES 2 | #define CHECK_YES 2 | |||
skipping to change at line 1039 | skipping to change at line 1040 | |||
/* keep the footnote label */ | /* keep the footnote label */ | |||
for (j=i=p->dle+1; T(p->text)[j] != ']'; j++) | for (j=i=p->dle+1; T(p->text)[j] != ']'; j++) | |||
EXPAND(foot->tag) = T(p->text)[j]; | EXPAND(foot->tag) = T(p->text)[j]; | |||
EXPAND(foot->tag) = 0; | EXPAND(foot->tag) = 0; | |||
S(foot->tag)--; | S(foot->tag)--; | |||
/* consume the closing ]: */ | /* consume the closing ]: */ | |||
j = nextnonblank(p, j+2); | j = nextnonblank(p, j+2); | |||
if ( (f->flags & MKD_EXTRA_FOOTNOTE) && (T(foot->tag)[0] == '^') ) { | if ( is_flag_set(f->flags, MKD_EXTRA_FOOTNOTE) && (T(foot->tag)[0] == '^') ) { | |||
/* markdown extra footnote: All indented lines past this point; | /* markdown extra footnote: All indented lines past this point; | |||
* the first line includes the footnote reference, so we need to | * the first line includes the footnote reference, so we need to | |||
* snip that out as we go. | * snip that out as we go. | |||
*/ | */ | |||
foot->flags |= EXTRA_FOOTNOTE; | foot->flags |= EXTRA_FOOTNOTE; | |||
__mkd_trim_line(p,j); | __mkd_trim_line(p,j); | |||
np = extrablock(p); | np = extrablock(p); | |||
foot->text = compile(p, 0, f); | foot->text = compile(p, 0, f); | |||
skipping to change at line 1124 | skipping to change at line 1125 | |||
int blanks=0; | int blanks=0; | |||
for (; ptr && blankline(ptr); ptr = next, blanks++ ) { | for (; ptr && blankline(ptr); ptr = next, blanks++ ) { | |||
next = ptr->next; | next = ptr->next; | |||
___mkd_freeLine(ptr); | ___mkd_freeLine(ptr); | |||
} | } | |||
if ( ptr ) *eaten = blanks; | if ( ptr ) *eaten = blanks; | |||
return ptr; | return ptr; | |||
} | } | |||
typedef ANCHOR(Line) Cache; | ||||
static void | ||||
uncache(Cache *cache, ParagraphRoot *d, MMIOT *f) | ||||
{ | ||||
Paragraph *p; | ||||
if ( T(*cache) ) { | ||||
E(*cache)->next = 0; | ||||
p = Pp(d, 0, SOURCE); | ||||
p->down = compile(T(*cache), 1, f); | ||||
T(*cache) = E(*cache) = 0; | ||||
} | ||||
} | ||||
/* | /* | |||
* top-level compilation; break the document into | * top-level compilation; break the document into | |||
* style, html, and source blocks with footnote links | * style, html, and source blocks with footnote links | |||
* weeded out. | * weeded out. | |||
*/ | */ | |||
static Paragraph * | static Paragraph * | |||
compile_document(Line *ptr, MMIOT *f) | compile_document(Line *ptr, MMIOT *f) | |||
{ | { | |||
ParagraphRoot d = { 0, 0 }; | ParagraphRoot d = { 0, 0 }; | |||
ANCHOR(Line) source = { 0, 0 }; | Cache source = { 0, 0 }; | |||
Paragraph *p = 0; | Paragraph *p = 0; | |||
struct kw *tag; | struct kw *tag; | |||
int eaten, unclosed; | int eaten, unclosed; | |||
int previous_was_break = 1; | ||||
while ( ptr ) { | while ( ptr ) { | |||
if ( !(f->flags & MKD_NOHTML) && (tag = isopentag(ptr)) ) { | if ( !is_flag_set(f->flags, MKD_NOHTML) && (tag = isopentag(ptr)) ) { | |||
int blocktype; | int blocktype; | |||
/* If we encounter a html/style block, compile and save all | /* If we encounter a html/style block, compile and save all | |||
* of the cached source BEFORE processing the html/style. | * of the cached source BEFORE processing the html/style. | |||
*/ | */ | |||
if ( T(source) ) { | uncache(&source, &d, f); | |||
E(source)->next = 0; | ||||
p = Pp(&d, 0, SOURCE); | ||||
p->down = compile(T(source), 1, f); | ||||
T(source) = E(source) = 0; | ||||
} | ||||
if ( f->flags & MKD_NOSTYLE ) | if (is_flag_set(f->flags, MKD_NOSTYLE) ) | |||
blocktype = HTML; | blocktype = HTML; | |||
else | else | |||
blocktype = strcmp(tag->id, "STYLE") == 0 ? STYLE : HTML; | blocktype = strcmp(tag->id, "STYLE") == 0 ? STYLE : HTML; | |||
p = Pp(&d, ptr, blocktype); | p = Pp(&d, ptr, blocktype); | |||
ptr = htmlblock(p, tag, &unclosed); | ptr = htmlblock(p, tag, &unclosed); | |||
if ( unclosed ) { | if ( unclosed ) { | |||
p->typ = SOURCE; | p->typ = SOURCE; | |||
p->down = compile(p->text, 1, f); | p->down = compile(p->text, 1, f); | |||
p->text = 0; | p->text = 0; | |||
} | } | |||
previous_was_break = 1; | ||||
} | } | |||
else if ( isfootnote(ptr) ) { | else if ( isfootnote(ptr) ) { | |||
/* footnotes, like cats, sleep anywhere; pull them | /* footnotes, like cats, sleep anywhere; pull them | |||
* out of the input stream and file them away for | * out of the input stream and file them away for | |||
* later processing | * later processing | |||
*/ | */ | |||
ptr = consume(addfootnote(ptr, f), &eaten); | ptr = consume(addfootnote(ptr, f), &eaten); | |||
previous_was_break = 1; | ||||
} | ||||
else if ( previous_was_break && iscodefence(ptr,3,0,f->flags)) { | ||||
uncache(&source, &d, f); | ||||
if ( !fencedcodeblock(&d, &ptr, f->flags) ) /* just source */ | ||||
goto attach; | ||||
} | } | |||
else { | else { | |||
attach: | ||||
/* source; cache it up to wait for eof or the | /* source; cache it up to wait for eof or the | |||
* next html/style block | * next html/style block | |||
*/ | */ | |||
ATTACH(source,ptr); | ATTACH(source,ptr); | |||
previous_was_break = blankline(ptr); | ||||
ptr = ptr->next; | ptr = ptr->next; | |||
} | } | |||
} | } | |||
if ( T(source) ) { | /* if there's any cached source at EOF, compile | |||
/* if there's any cached source at EOF, compile | * it now. | |||
* it now. | */ | |||
*/ | uncache(&source, &d, f); | |||
E(source)->next = 0; | ||||
p = Pp(&d, 0, SOURCE); | ||||
p->down = compile(T(source), 1, f); | ||||
} | ||||
return T(d); | return T(d); | |||
} | } | |||
static int | static int | |||
first_nonblank_before(Line *j, int dle) | first_nonblank_before(Line *j, int dle) | |||
{ | { | |||
return (j->dle < dle) ? j->dle : dle; | return (j->dle < dle) ? j->dle : dle; | |||
} | } | |||
static int | static int | |||
actually_a_table(MMIOT *f, Line *pp) | actually_a_table(MMIOT *f, Line *pp) | |||
{ | { | |||
Line *r; | Line *r; | |||
int j; | int j; | |||
int c; | int c; | |||
/* tables need to be turned on */ | /* tables need to be turned on */ | |||
if ( f->flags & (MKD_STRICT|MKD_NOTABLES) ) | if ( is_flag_set(f->flags, MKD_STRICT) || is_flag_set(f->flags, MKD_NOTABLES ) ) | |||
return 0; | return 0; | |||
/* tables need three lines */ | /* tables need three lines */ | |||
if ( !(pp && pp->next && pp->next->next) ) { | if ( !(pp && pp->next && pp->next->next) ) { | |||
return 0; | return 0; | |||
} | } | |||
/* all lines must contain |'s */ | /* all lines must contain |'s */ | |||
for (r = pp; r; r = r->next ) | for (r = pp; r; r = r->next ) | |||
if ( !(r->flags & PIPECHAR) ) { | if ( !(r->flags & PIPECHAR) ) { | |||
skipping to change at line 1261 | skipping to change at line 1278 | |||
int blocks = 0; | int blocks = 0; | |||
int hdr_type, list_type, list_class, indent; | int hdr_type, list_type, list_class, indent; | |||
ptr = consume(ptr, ¶); | ptr = consume(ptr, ¶); | |||
while ( ptr ) { | while ( ptr ) { | |||
if ( iscode(ptr) ) { | if ( iscode(ptr) ) { | |||
p = Pp(&d, ptr, CODE); | p = Pp(&d, ptr, CODE); | |||
if ( f->flags & MKD_1_COMPAT) { | if ( is_flag_set(f->flags, MKD_1_COMPAT) ) { | |||
/* HORRIBLE STANDARDS KLUDGE: the first line of every block | /* HORRIBLE STANDARDS KLUDGE: the first line of every block | |||
* has trailing whitespace trimmed off. | * has trailing whitespace trimmed off. | |||
*/ | */ | |||
___mkd_tidy(&p->text->text); | ___mkd_tidy(&p->text->text); | |||
} | } | |||
ptr = codeblock(p); | ptr = codeblock(p); | |||
} | } | |||
else if ( iscodefence(ptr,3,0,f->flags) && (p=fencedcodeblock(&d, &ptr, f ->flags)) ) | else if ( iscodefence(ptr,3,0,f->flags) && (p=fencedcodeblock(&d, &ptr, f ->flags)) ) | |||
/* yay, it's already done */ ; | /* yay, it's already done */ ; | |||
skipping to change at line 1316 | skipping to change at line 1333 | |||
* block. If it IS an html | * block. If it IS an html | |||
* block, htmlblock() will | * block, htmlblock() will | |||
* populate this paragraph & | * populate this paragraph & | |||
* all we need to do is reset | * all we need to do is reset | |||
* the paragraph type to HTML, | * the paragraph type to HTML, | |||
* otherwise the paragraph | * otherwise the paragraph | |||
* remains empty and ready for | * remains empty and ready for | |||
* processing with textblock() | * processing with textblock() | |||
*/ | */ | |||
if ( !(f->flags & MKD_NOHTML) && (tag = isopentag(ptr)) ) { | if ( !is_flag_set(f->flags, MKD_NOHTML) && (tag = isopentag(ptr)) ) { | |||
/* possibly an html block | /* possibly an html block | |||
*/ | */ | |||
ptr = htmlblock(p, tag, &unclosed); | ptr = htmlblock(p, tag, &unclosed); | |||
if ( ! unclosed ) { | if ( ! unclosed ) { | |||
p->typ = HTML; | p->typ = HTML; | |||
} | } | |||
} | } | |||
if ( unclosed ) { | if ( unclosed ) { | |||
ptr = textblock(p, toplevel, f->flags); | ptr = textblock(p, toplevel, f->flags); | |||
skipping to change at line 1355 | skipping to change at line 1372 | |||
/* | /* | |||
* the guts of the markdown() function, ripped out so I can do | * the guts of the markdown() function, ripped out so I can do | |||
* debugging. | * debugging. | |||
*/ | */ | |||
/* | /* | |||
* prepare and compile `text`, returning a Paragraph tree. | * prepare and compile `text`, returning a Paragraph tree. | |||
*/ | */ | |||
int | int | |||
mkd_compile(Document *doc, DWORD flags) | mkd_compile(Document *doc, mkd_flag_t flags) | |||
{ | { | |||
if ( !doc ) | if ( !doc ) | |||
return 0; | return 0; | |||
flags &= USER_FLAGS; | flags &= USER_FLAGS; | |||
if ( doc->compiled ) { | if ( doc->compiled ) { | |||
if ( doc->ctx->flags == flags && !doc->dirty) | if ( doc->ctx->flags == flags && !doc->dirty) | |||
return 1; | return 1; | |||
else { | else { | |||
End of changes. 40 change blocks. | ||||
48 lines changed or deleted | 65 lines changed or added |