bluecloth 2.0.5 → 2.0.6.pre120
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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);
|