bluecloth 2.0.5 → 2.0.6.pre120
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +242 -678
- data/LICENSE +1 -1
- data/README +2 -2
- data/Rakefile +99 -68
- data/Rakefile.local +21 -41
- data/ext/VERSION +1 -1
- data/ext/bluecloth.c +18 -4
- data/ext/bluecloth.h +19 -0
- data/ext/config.h +8 -0
- data/ext/cstring.h +3 -2
- data/ext/extconf.rb +8 -1
- data/ext/generate.c +148 -27
- data/ext/markdown.c +135 -27
- data/ext/markdown.h +3 -2
- data/ext/mkdio.h +1 -0
- data/lib/bluecloth.rb +12 -9
- data/rake/dependencies.rb +1 -1
- data/rake/helpers.rb +24 -2
- data/rake/hg.rb +273 -0
- data/rake/manual.rb +3 -3
- data/rake/packaging.rb +33 -35
- data/rake/publishing.rb +16 -68
- data/rake/rdoc.rb +1 -1
- data/rake/style.rb +1 -1
- data/rake/svn.rb +577 -549
- data/rake/testing.rb +4 -20
- data/rake/win32.rb +13 -9
- data/spec/bluecloth/blockquotes_spec.rb +24 -22
- data/spec/bluecloth_spec.rb +31 -0
- data/spec/bugfix_spec.rb +37 -1
- data/spec/discount_spec.rb +117 -0
- data/spec/markdowntest_spec.rb +8 -8
- metadata +19 -138
data/ext/bluecloth.h
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
/*
|
2
|
+
* BlueCloth -- a Ruby implementation of Markdown
|
3
|
+
* $Id$
|
4
|
+
*
|
5
|
+
*/
|
6
|
+
|
7
|
+
#ifndef BLUECLOTH_H
|
8
|
+
#define BLUECLOTH_H
|
9
|
+
|
10
|
+
#include "config.h"
|
11
|
+
|
12
|
+
#include "mkdio.h"
|
13
|
+
#include "ruby.h"
|
14
|
+
|
15
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
16
|
+
# include "ruby/encoding.h"
|
17
|
+
#endif
|
18
|
+
|
19
|
+
#endif
|
data/ext/config.h
CHANGED
@@ -6,6 +6,10 @@
|
|
6
6
|
#ifndef CONFIG_H_RZLE3ADO
|
7
7
|
#define CONFIG_H_RZLE3ADO
|
8
8
|
|
9
|
+
#ifdef RUBY_EXTCONF_H
|
10
|
+
# include RUBY_EXTCONF_H
|
11
|
+
#endif
|
12
|
+
|
9
13
|
#ifdef HAVE_SRANDOM
|
10
14
|
# define INITRNG(x) srandom((unsigned int)x)
|
11
15
|
#elif HAVE_SRAND
|
@@ -14,6 +18,10 @@
|
|
14
18
|
# define INITRNG(x) (void)1
|
15
19
|
#endif
|
16
20
|
|
21
|
+
#ifndef HAVE_BZERO
|
22
|
+
# define bzero(s, n) (memset((void *)s, 0, (size_t)n))
|
23
|
+
#endif
|
24
|
+
|
17
25
|
#ifdef HAVE_STRCASECMP
|
18
26
|
#elif HAVE_STRICMP
|
19
27
|
# define strcasecmp stricmp
|
data/ext/cstring.h
CHANGED
@@ -60,9 +60,10 @@
|
|
60
60
|
* macro will work with it.
|
61
61
|
*/
|
62
62
|
#define ANCHOR(t) struct { t *text, *end; }
|
63
|
+
#define E(t) ((t).end)
|
63
64
|
|
64
|
-
#define ATTACH(t, p) ( (t)
|
65
|
-
|
65
|
+
#define ATTACH(t, p) ( T(t) ? ( (E(t)->next = (p)), (E(t) = (p)) ) \
|
66
|
+
: ( (T(t) = E(t) = (p)) ) )
|
66
67
|
|
67
68
|
typedef STRING(char) Cstring;
|
68
69
|
|
data/ext/extconf.rb
CHANGED
@@ -19,7 +19,7 @@ $CPPFLAGS << %Q{ -DVERSION=\\"#{version}\\"}
|
|
19
19
|
|
20
20
|
# Add my own debugging hooks if building for me
|
21
21
|
if ENV['DEBUGGING_BUILD']
|
22
|
-
$CFLAGS << ' -ggdb' << ' -DDEBUG'
|
22
|
+
$CFLAGS << ' -ggdb' << ' -DDEBUG'
|
23
23
|
end
|
24
24
|
|
25
25
|
def fail( *messages )
|
@@ -31,6 +31,9 @@ end
|
|
31
31
|
have_func( "srand" ) || have_func( "srandom" )
|
32
32
|
have_func( "random" ) || have_func( "rand" )
|
33
33
|
|
34
|
+
# bzero() isn't ANSI C, so use memset() if it isn't defined
|
35
|
+
have_func( "bzero", %w[string.h strings.h] )
|
36
|
+
|
34
37
|
unless have_func( "strcasecmp" ) || have_func( "stricmp" )
|
35
38
|
fail( "This extension requires either strcasecmp() or stricmp()" )
|
36
39
|
end
|
@@ -40,6 +43,10 @@ end
|
|
40
43
|
|
41
44
|
have_header( 'mkdio.h' ) or fail( "missing mkdio.h" )
|
42
45
|
|
46
|
+
# Check for 1.9.xish encoding header
|
47
|
+
have_header( 'ruby/encoding.h' )
|
48
|
+
|
49
|
+
create_header()
|
43
50
|
create_makefile( 'bluecloth_ext' )
|
44
51
|
|
45
52
|
FileUtils.rm_rf( 'conftest.dSYM' ) # MacOS X cleanup
|
data/ext/generate.c
CHANGED
@@ -632,9 +632,9 @@ linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref)
|
|
632
632
|
|
633
633
|
Qstring(tag->link_sfx, f);
|
634
634
|
|
635
|
-
if ( tag->WxH
|
636
|
-
Qprintf(f," height=\"%d\"", ref->height);
|
637
|
-
Qprintf(f, " width=\"%d\"", ref->width);
|
635
|
+
if ( tag->WxH) {
|
636
|
+
if ( ref->height) Qprintf(f," height=\"%d\"", ref->height);
|
637
|
+
if ( ref->width) Qprintf(f, " width=\"%d\"", ref->width);
|
638
638
|
}
|
639
639
|
|
640
640
|
if ( S(ref->title) ) {
|
@@ -661,44 +661,46 @@ static int
|
|
661
661
|
linkylinky(int image, MMIOT *f)
|
662
662
|
{
|
663
663
|
int start = mmiottell(f);
|
664
|
-
int implicit_mark;
|
665
664
|
Cstring name;
|
666
665
|
Footnote key, *ref;
|
667
666
|
|
668
667
|
int status = 0;
|
669
668
|
|
670
669
|
CREATE(name);
|
671
|
-
|
670
|
+
memset(&key, 0, sizeof key);
|
672
671
|
|
673
672
|
if ( linkylabel(f, &name) ) {
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
switch ( pull(f) ) {
|
678
|
-
case '(': /* embedded link */
|
673
|
+
if ( peek(f,1) == '(' ) {
|
674
|
+
pull(f);
|
679
675
|
if ( linkyurl(f, image, &key) )
|
680
676
|
status = linkyformat(f, name, image, &key);
|
681
|
-
|
677
|
+
}
|
678
|
+
else {
|
679
|
+
int goodlink, implicit_mark = mmiottell(f);
|
682
680
|
|
683
|
-
|
684
|
-
|
685
|
-
|
681
|
+
if ( eatspace(f) == '[' ) {
|
682
|
+
pull(f); /* consume leading '[' */
|
683
|
+
goodlink = linkylabel(f, &key.tag);
|
684
|
+
}
|
685
|
+
else {
|
686
|
+
/* new markdown implicit name syntax doesn't
|
687
|
+
* require a second []
|
688
|
+
*/
|
686
689
|
mmiotseek(f, implicit_mark);
|
687
|
-
|
688
|
-
break;
|
690
|
+
goodlink = !(f->flags & MKD_1_COMPAT);
|
689
691
|
}
|
690
|
-
else if ( !linkylabel(f, &key.tag) )
|
691
|
-
break;
|
692
692
|
|
693
|
-
if (
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
693
|
+
if ( goodlink ) {
|
694
|
+
if ( !S(key.tag) ) {
|
695
|
+
DELETE(key.tag);
|
696
|
+
T(key.tag) = T(name);
|
697
|
+
S(key.tag) = S(name);
|
698
|
+
}
|
698
699
|
|
699
|
-
|
700
|
-
|
701
|
-
|
700
|
+
if ( ref = bsearch(&key, T(*f->footnotes), S(*f->footnotes),
|
701
|
+
sizeof key, (stfu)__mkd_footsort) )
|
702
|
+
status = linkyformat(f, name, image, ref);
|
703
|
+
}
|
702
704
|
}
|
703
705
|
}
|
704
706
|
|
@@ -867,9 +869,19 @@ maybe_tag_or_link(MMIOT *f)
|
|
867
869
|
|
868
870
|
if ( size ) {
|
869
871
|
if ( maybetag || (size >= 3 && strncmp(cursor(f), "!--", 3) == 0) ) {
|
872
|
+
|
873
|
+
/* It is not a html tag unless we find the closing '>' in
|
874
|
+
* the same block.
|
875
|
+
*/
|
876
|
+
while ( (c = peek(f, size+1)) != '>' )
|
877
|
+
if ( c == EOF )
|
878
|
+
return 0;
|
879
|
+
else
|
880
|
+
size++;
|
881
|
+
|
870
882
|
Qstring(forbidden_tag(f) ? "<" : "<", f);
|
871
883
|
while ( ((c = peek(f, 1)) != EOF) && (c != '>') )
|
872
|
-
|
884
|
+
Qchar(pull(f), f);
|
873
885
|
return 1;
|
874
886
|
}
|
875
887
|
else if ( !isspace(c) && process_possible_link(f, size) ) {
|
@@ -1276,6 +1288,106 @@ printheader(Paragraph *pp, MMIOT *f)
|
|
1276
1288
|
}
|
1277
1289
|
|
1278
1290
|
|
1291
|
+
enum e_alignments { a_NONE, a_CENTER, a_LEFT, a_RIGHT };
|
1292
|
+
|
1293
|
+
static char* alignments[] = { "", " align=\"center\"", " align=\"left\"",
|
1294
|
+
" align=\"right\"" };
|
1295
|
+
|
1296
|
+
typedef STRING(int) Istring;
|
1297
|
+
|
1298
|
+
static int
|
1299
|
+
splat(Line *p, char *block, Istring align, int force, MMIOT *f)
|
1300
|
+
{
|
1301
|
+
int first,
|
1302
|
+
idx = 0,
|
1303
|
+
colno = 0;
|
1304
|
+
|
1305
|
+
Qstring("<tr>\n", f);
|
1306
|
+
while ( idx < S(p->text) ) {
|
1307
|
+
first = idx;
|
1308
|
+
if ( force && (colno >= S(align)-1) )
|
1309
|
+
idx = S(p->text);
|
1310
|
+
else
|
1311
|
+
while ( (idx < S(p->text)) && (T(p->text)[idx] != '|') )
|
1312
|
+
++idx;
|
1313
|
+
|
1314
|
+
Qprintf(f, "<%s%s>",
|
1315
|
+
block,
|
1316
|
+
alignments[ (colno < S(align)) ? T(align)[colno] : a_NONE ]);
|
1317
|
+
___mkd_reparse(T(p->text)+first, idx-first, 0, f);
|
1318
|
+
Qprintf(f, "</%s>\n", block);
|
1319
|
+
idx++;
|
1320
|
+
colno++;
|
1321
|
+
}
|
1322
|
+
if ( force )
|
1323
|
+
while (colno < S(align) ) {
|
1324
|
+
Qprintf(f, "<%s></%s>\n", block, block);
|
1325
|
+
++colno;
|
1326
|
+
}
|
1327
|
+
Qstring("</tr>\n", f);
|
1328
|
+
return colno;
|
1329
|
+
}
|
1330
|
+
|
1331
|
+
static int
|
1332
|
+
printtable(Paragraph *pp, MMIOT *f)
|
1333
|
+
{
|
1334
|
+
/* header, dashes, then lines of content */
|
1335
|
+
|
1336
|
+
Line *hdr, *dash, *body;
|
1337
|
+
Istring align;
|
1338
|
+
int start;
|
1339
|
+
int hcols;
|
1340
|
+
char *p;
|
1341
|
+
|
1342
|
+
if ( !(pp->text && pp->text->next) )
|
1343
|
+
return 0;
|
1344
|
+
|
1345
|
+
hdr = pp->text;
|
1346
|
+
dash= hdr->next;
|
1347
|
+
body= dash->next;
|
1348
|
+
|
1349
|
+
/* first figure out cell alignments */
|
1350
|
+
|
1351
|
+
CREATE(align);
|
1352
|
+
|
1353
|
+
for (p=T(dash->text), start=0; start < S(dash->text); ) {
|
1354
|
+
char first, last;
|
1355
|
+
int end;
|
1356
|
+
|
1357
|
+
last=first=0;
|
1358
|
+
for (end=start ; (end < S(dash->text)) && p[end] != '|'; ++ end ) {
|
1359
|
+
if ( !isspace(p[end]) ) {
|
1360
|
+
if ( !first) first = p[end];
|
1361
|
+
last = p[end];
|
1362
|
+
}
|
1363
|
+
}
|
1364
|
+
EXPAND(align) = ( first == ':' ) ? (( last == ':') ? a_CENTER : a_LEFT)
|
1365
|
+
: (( last == ':') ? a_RIGHT : a_NONE );
|
1366
|
+
start = 1+end;
|
1367
|
+
}
|
1368
|
+
|
1369
|
+
Qstring("<table>\n", f);
|
1370
|
+
Qstring("<thead>\n", f);
|
1371
|
+
hcols = splat(hdr, "th", align, 0, f);
|
1372
|
+
Qstring("</thead>\n", f);
|
1373
|
+
|
1374
|
+
if ( hcols < S(align) )
|
1375
|
+
S(align) = hcols;
|
1376
|
+
else
|
1377
|
+
while ( hcols > S(align) )
|
1378
|
+
EXPAND(align) = a_NONE;
|
1379
|
+
|
1380
|
+
Qstring("<tbody>\n", f);
|
1381
|
+
for ( ; body; body = body->next)
|
1382
|
+
splat(body, "td", align, 1, f);
|
1383
|
+
Qstring("</tbody>\n", f);
|
1384
|
+
Qstring("</table>\n", f);
|
1385
|
+
|
1386
|
+
DELETE(align);
|
1387
|
+
return 1;
|
1388
|
+
}
|
1389
|
+
|
1390
|
+
|
1279
1391
|
static int
|
1280
1392
|
printblock(Paragraph *pp, MMIOT *f)
|
1281
1393
|
{
|
@@ -1382,6 +1494,7 @@ definitionlist(Paragraph *p, MMIOT *f)
|
|
1382
1494
|
}
|
1383
1495
|
|
1384
1496
|
htmlify(p->down, "dd", p->ident, f);
|
1497
|
+
Qchar('\n', f);
|
1385
1498
|
}
|
1386
1499
|
|
1387
1500
|
Qstring("</dl>", f);
|
@@ -1453,6 +1566,14 @@ display(Paragraph *p, MMIOT *f)
|
|
1453
1566
|
printheader(p, f);
|
1454
1567
|
break;
|
1455
1568
|
|
1569
|
+
case TABLE:
|
1570
|
+
printtable(p, f);
|
1571
|
+
break;
|
1572
|
+
|
1573
|
+
case SOURCE:
|
1574
|
+
htmlify(p->down, 0, 0, f);
|
1575
|
+
break;
|
1576
|
+
|
1456
1577
|
default:
|
1457
1578
|
printblock(p, f);
|
1458
1579
|
break;
|
data/ext/markdown.c
CHANGED
@@ -32,11 +32,11 @@ static struct kw blocktags[] = { KW("!--"), KW("STYLE"), KW("SCRIPT"),
|
|
32
32
|
KW("ADDRESS"), KW("BDO"), KW("BLOCKQUOTE"),
|
33
33
|
KW("CENTER"), KW("DFN"), KW("DIV"), KW("H1"),
|
34
34
|
KW("H2"), KW("H3"), KW("H4"), KW("H5"),
|
35
|
-
KW("H6"), KW("
|
35
|
+
KW("H6"), KW("LISTING"), KW("NOBR"),
|
36
36
|
KW("UL"), KW("P"), KW("OL"), KW("DL"),
|
37
37
|
KW("PLAINTEXT"), KW("PRE"), KW("TABLE"),
|
38
38
|
KW("WBR"), KW("XMP"), SC("HR"), SC("BR"),
|
39
|
-
KW("MAP") };
|
39
|
+
KW("IFRAME"), KW("MAP") };
|
40
40
|
#define SZTAGS (sizeof blocktags / sizeof blocktags[0])
|
41
41
|
#define MAXTAG 11 /* sizeof "BLOCKQUOTE" */
|
42
42
|
|
@@ -230,6 +230,8 @@ htmlblock(Paragraph *p, struct kw *tag)
|
|
230
230
|
/* consume trailing gunk in close tag */
|
231
231
|
c = flogetc(&f);
|
232
232
|
}
|
233
|
+
if ( !f.t )
|
234
|
+
return 0;
|
233
235
|
ret = f.t->next;
|
234
236
|
f.t->next = 0;
|
235
237
|
return ret;
|
@@ -259,6 +261,37 @@ comment(Paragraph *p)
|
|
259
261
|
}
|
260
262
|
|
261
263
|
|
264
|
+
/* tables look like
|
265
|
+
* header|header{|header}
|
266
|
+
* ------|------{|......}
|
267
|
+
* {body lines}
|
268
|
+
*/
|
269
|
+
static int
|
270
|
+
istable(Line *t)
|
271
|
+
{
|
272
|
+
char *p;
|
273
|
+
Line *dashes = t->next;
|
274
|
+
int contains = 0; /* found character bits; 0x01 is |, 0x02 is - */
|
275
|
+
|
276
|
+
/* two lines, first must contain | */
|
277
|
+
if ( !(dashes && memchr(T(t->text), '|', S(t->text))) )
|
278
|
+
return 0;
|
279
|
+
|
280
|
+
/* second line must contain - or | and nothing
|
281
|
+
* else except for whitespace or :
|
282
|
+
*/
|
283
|
+
for ( p = T(dashes->text)+S(dashes->text)-1; p >= T(dashes->text); --p)
|
284
|
+
if ( *p == '|' )
|
285
|
+
contains |= 0x01;
|
286
|
+
else if ( *p == '-' )
|
287
|
+
contains |= 0x02;
|
288
|
+
else if ( ! ((*p == ':') || isspace(*p)) )
|
289
|
+
return 0;
|
290
|
+
|
291
|
+
return (contains & 0x03);
|
292
|
+
}
|
293
|
+
|
294
|
+
|
262
295
|
/* footnotes look like ^<whitespace>{0,3}[stuff]: <content>$
|
263
296
|
*/
|
264
297
|
static int
|
@@ -554,17 +587,17 @@ szmarkerclass(char *p)
|
|
554
587
|
* marker %[kind:]name%
|
555
588
|
*/
|
556
589
|
static int
|
557
|
-
isdivmarker(Line *p)
|
590
|
+
isdivmarker(Line *p, int start)
|
558
591
|
{
|
559
592
|
#if DIV_QUOTE
|
560
593
|
char *s = T(p->text);
|
561
594
|
int len = S(p->text);
|
562
595
|
int i;
|
563
596
|
|
564
|
-
if ( !(len && s[
|
597
|
+
if ( !(len && s[start] == '%' && s[len-1] == '%') ) return 0;
|
565
598
|
|
566
|
-
i = szmarkerclass(s+1);
|
567
|
-
|
599
|
+
i = szmarkerclass(s+start+1)+start;
|
600
|
+
len -= start+1;
|
568
601
|
|
569
602
|
while ( ++i < len )
|
570
603
|
if ( !isalnum(s[i]) )
|
@@ -601,13 +634,15 @@ quoteblock(Paragraph *p)
|
|
601
634
|
t->dle = mkd_firstnonblank(t);
|
602
635
|
}
|
603
636
|
|
604
|
-
|
637
|
+
q = skipempty(t->next);
|
638
|
+
|
639
|
+
if ( (q == 0) || ((q != t->next) && (!isquote(q) || isdivmarker(q,1))) ) {
|
605
640
|
___mkd_freeLineRange(t, q);
|
606
641
|
t = q;
|
607
642
|
break;
|
608
643
|
}
|
609
644
|
}
|
610
|
-
if ( isdivmarker(p->text) ) {
|
645
|
+
if ( isdivmarker(p->text,0) ) {
|
611
646
|
char *prefix = "class";
|
612
647
|
int i;
|
613
648
|
|
@@ -628,6 +663,25 @@ quoteblock(Paragraph *p)
|
|
628
663
|
}
|
629
664
|
|
630
665
|
|
666
|
+
/*
|
667
|
+
* A table block starts with a table header (see istable()), and continues
|
668
|
+
* until EOF or a line that /doesn't/ contain a |.
|
669
|
+
*/
|
670
|
+
static Line *
|
671
|
+
tableblock(Paragraph *p)
|
672
|
+
{
|
673
|
+
Line *t, *q;
|
674
|
+
|
675
|
+
for ( t = p->text; t && (q = t->next); t = t->next ) {
|
676
|
+
if ( !memchr(T(q->text), '|', S(q->text)) ) {
|
677
|
+
t->next = 0;
|
678
|
+
return q;
|
679
|
+
}
|
680
|
+
}
|
681
|
+
return 0;
|
682
|
+
}
|
683
|
+
|
684
|
+
|
631
685
|
static Paragraph *Pp(ParagraphRoot *, Line *, int);
|
632
686
|
static Paragraph *compile(Line *, int, MMIOT *);
|
633
687
|
|
@@ -659,7 +713,7 @@ listitem(Paragraph *p, int indent)
|
|
659
713
|
* need any indentation
|
660
714
|
*/
|
661
715
|
if ( q != t->next ) {
|
662
|
-
if (q->dle <
|
716
|
+
if (q->dle < indent) {
|
663
717
|
q = t->next;
|
664
718
|
t->next = 0;
|
665
719
|
return q;
|
@@ -684,9 +738,10 @@ listblock(Paragraph *top, int trim, MMIOT *f)
|
|
684
738
|
{
|
685
739
|
ParagraphRoot d = { 0, 0 };
|
686
740
|
Paragraph *p;
|
687
|
-
Line *q = top->text, *text;
|
688
|
-
|
689
|
-
|
741
|
+
Line *q = top->text, *text, *label;
|
742
|
+
int isdl = (top->typ == DL),
|
743
|
+
para = 0,
|
744
|
+
ltype;
|
690
745
|
|
691
746
|
while (( text = q )) {
|
692
747
|
if ( top->typ == DL ) {
|
@@ -710,7 +765,8 @@ listblock(Paragraph *top, int trim, MMIOT *f)
|
|
710
765
|
|
711
766
|
if ( para && (top->typ != DL) && p->down ) p->down->align = PARA;
|
712
767
|
|
713
|
-
if ( !(q = skipempty(text)) || (islist(q, &trim) == 0)
|
768
|
+
if ( !(q = skipempty(text)) || ((ltype = islist(q, &trim)) == 0)
|
769
|
+
|| (isdl != (ltype == DL)) )
|
714
770
|
break;
|
715
771
|
|
716
772
|
if ( para = (q != text) ) {
|
@@ -840,6 +896,64 @@ consume(Line *ptr, int *eaten)
|
|
840
896
|
}
|
841
897
|
|
842
898
|
|
899
|
+
/*
|
900
|
+
* top-level compilation; break the document into
|
901
|
+
* style, html, and source blocks with footnote links
|
902
|
+
* weeded out.
|
903
|
+
*/
|
904
|
+
static Paragraph *
|
905
|
+
compile_document(Line *ptr, MMIOT *f)
|
906
|
+
{
|
907
|
+
ParagraphRoot d = { 0, 0 };
|
908
|
+
ANCHOR(Line) source = { 0, 0 };
|
909
|
+
Paragraph *p = 0;
|
910
|
+
struct kw *tag;
|
911
|
+
int eaten;
|
912
|
+
|
913
|
+
while ( ptr ) {
|
914
|
+
if ( !(f->flags & DENY_HTML) && (tag = isopentag(ptr)) ) {
|
915
|
+
/* If we encounter a html/style block, compile and save all
|
916
|
+
* of the cached source BEFORE processing the html/style.
|
917
|
+
*/
|
918
|
+
if ( T(source) ) {
|
919
|
+
E(source)->next = 0;
|
920
|
+
p = Pp(&d, 0, SOURCE);
|
921
|
+
p->down = compile(T(source), 1, f);
|
922
|
+
T(source) = E(source) = 0;
|
923
|
+
}
|
924
|
+
p = Pp(&d, ptr, strcmp(tag->id, "STYLE") == 0 ? STYLE : HTML);
|
925
|
+
if ( strcmp(tag->id, "!--") == 0 )
|
926
|
+
ptr = comment(p);
|
927
|
+
else
|
928
|
+
ptr = htmlblock(p, tag);
|
929
|
+
}
|
930
|
+
else if ( isfootnote(ptr) ) {
|
931
|
+
/* footnotes, like cats, sleep anywhere; pull them
|
932
|
+
* out of the input stream and file them away for
|
933
|
+
* later processing
|
934
|
+
*/
|
935
|
+
ptr = consume(addfootnote(ptr, f), &eaten);
|
936
|
+
}
|
937
|
+
else {
|
938
|
+
/* source; cache it up to wait for eof or the
|
939
|
+
* next html/style block
|
940
|
+
*/
|
941
|
+
ATTACH(source,ptr);
|
942
|
+
ptr = ptr->next;
|
943
|
+
}
|
944
|
+
}
|
945
|
+
if ( T(source) ) {
|
946
|
+
/* if there's any cached source at EOF, compile
|
947
|
+
* it now.
|
948
|
+
*/
|
949
|
+
E(source)->next = 0;
|
950
|
+
p = Pp(&d, 0, SOURCE);
|
951
|
+
p->down = compile(T(source), 1, f);
|
952
|
+
}
|
953
|
+
return T(d);
|
954
|
+
}
|
955
|
+
|
956
|
+
|
843
957
|
/*
|
844
958
|
* break a collection of markdown input into
|
845
959
|
* blocks of lists, code, html, and text to
|
@@ -850,22 +964,15 @@ compile(Line *ptr, int toplevel, MMIOT *f)
|
|
850
964
|
{
|
851
965
|
ParagraphRoot d = { 0, 0 };
|
852
966
|
Paragraph *p = 0;
|
853
|
-
struct kw *tag;
|
854
967
|
Line *r;
|
855
968
|
int para = toplevel;
|
969
|
+
int blocks = 0;
|
856
970
|
int hdr_type, list_type, indent;
|
857
971
|
|
858
972
|
ptr = consume(ptr, ¶);
|
859
973
|
|
860
974
|
while ( ptr ) {
|
861
|
-
if (
|
862
|
-
p = Pp(&d, ptr, strcmp(tag->id, "STYLE") == 0 ? STYLE : HTML);
|
863
|
-
if ( strcmp(tag->id, "!--") == 0 )
|
864
|
-
ptr = comment(p);
|
865
|
-
else
|
866
|
-
ptr = htmlblock(p, tag);
|
867
|
-
}
|
868
|
-
else if ( iscode(ptr) ) {
|
975
|
+
if ( iscode(ptr) ) {
|
869
976
|
p = Pp(&d, ptr, CODE);
|
870
977
|
|
871
978
|
if ( f->flags & MKD_1_COMPAT) {
|
@@ -897,9 +1004,9 @@ compile(Line *ptr, int toplevel, MMIOT *f)
|
|
897
1004
|
p = Pp(&d, ptr, HDR);
|
898
1005
|
ptr = headerblock(p, hdr_type);
|
899
1006
|
}
|
900
|
-
else if (
|
901
|
-
|
902
|
-
|
1007
|
+
else if ( istable(ptr) && !(f->flags & (STRICT|NOTABLES)) ) {
|
1008
|
+
p = Pp(&d, ptr, TABLE);
|
1009
|
+
ptr = tableblock(p);
|
903
1010
|
}
|
904
1011
|
else {
|
905
1012
|
p = Pp(&d, ptr, MARKUP);
|
@@ -909,7 +1016,8 @@ compile(Line *ptr, int toplevel, MMIOT *f)
|
|
909
1016
|
if ( (para||toplevel) && !p->align )
|
910
1017
|
p->align = PARA;
|
911
1018
|
|
912
|
-
|
1019
|
+
blocks++;
|
1020
|
+
para = toplevel || (blocks > 1);
|
913
1021
|
ptr = consume(ptr, ¶);
|
914
1022
|
|
915
1023
|
if ( para && !p->align )
|
@@ -960,7 +1068,7 @@ mkd_compile(Document *doc, int flags)
|
|
960
1068
|
|
961
1069
|
initialize();
|
962
1070
|
|
963
|
-
doc->code =
|
1071
|
+
doc->code = compile_document(T(doc->content), doc->ctx);
|
964
1072
|
qsort(T(*doc->ctx->footnotes), S(*doc->ctx->footnotes),
|
965
1073
|
sizeof T(*doc->ctx->footnotes)[0],
|
966
1074
|
(stfu)__mkd_footsort);
|