rdiscount 2.2.0.2 → 2.2.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.markdown +11 -12
- data/Rakefile +11 -2
- data/bin/rdiscount +10 -3
- data/ext/Csio.c +2 -2
- data/ext/VERSION +1 -1
- data/ext/amalloc.c +1 -0
- data/ext/blocktags +2 -1
- data/ext/config.h +2 -0
- data/ext/css.c +5 -7
- data/ext/cstring.h +0 -1
- data/ext/docheader.c +6 -1
- data/ext/dumptree.c +11 -2
- data/ext/extconf.rb +1 -0
- data/ext/flags.c +4 -2
- data/ext/generate.c +339 -141
- data/ext/gethopt.c +286 -0
- data/ext/gethopt.h +43 -0
- data/ext/github_flavoured.c +8 -7
- data/ext/h1title.c +36 -0
- data/ext/html5.c +0 -1
- data/ext/markdown.c +189 -87
- data/ext/markdown.h +55 -27
- data/ext/mkdio.c +155 -58
- data/ext/mkdio.h +9 -5
- data/ext/mktags.c +3 -0
- data/ext/notspecial.c +44 -0
- data/ext/pgm_options.c +12 -12
- data/ext/pgm_options.h +2 -2
- data/ext/rdiscount.c +3 -0
- data/ext/resource.c +1 -0
- data/ext/setup.c +1 -1
- data/ext/tags.c +2 -0
- data/ext/toc.c +12 -14
- data/ext/version.c +3 -3
- data/ext/xml.c +6 -5
- data/ext/xmlpage.c +5 -8
- data/lib/rdiscount.rb +12 -1
- data/rdiscount.gemspec +8 -8
- data/test/markdown_test.rb +0 -1
- data/test/rdiscount_test.rb +46 -23
- metadata +10 -5
data/ext/markdown.c
CHANGED
@@ -147,12 +147,12 @@ typedef struct _flo {
|
|
147
147
|
#define floindex(x) (x.i)
|
148
148
|
|
149
149
|
|
150
|
-
static int
|
150
|
+
static unsigned int
|
151
151
|
flogetc(FLO *f)
|
152
152
|
{
|
153
153
|
if ( f && f->t ) {
|
154
154
|
if ( f->i < S(f->t->text) )
|
155
|
-
return T(f->t->text)[f->i++];
|
155
|
+
return (unsigned char)T(f->t->text)[f->i++];
|
156
156
|
f->t = f->t->next;
|
157
157
|
f->i = 0;
|
158
158
|
return flogetc(f);
|
@@ -170,8 +170,10 @@ splitline(Line *t, int cutpoint)
|
|
170
170
|
tmp->next = t->next;
|
171
171
|
t->next = tmp;
|
172
172
|
|
173
|
-
tmp->dle = t->dle;
|
174
173
|
SUFFIX(tmp->text, T(t->text)+cutpoint, S(t->text)-cutpoint);
|
174
|
+
EXPAND(tmp->text) = 0;
|
175
|
+
S(tmp->text)--;
|
176
|
+
|
175
177
|
S(t->text) = cutpoint;
|
176
178
|
}
|
177
179
|
}
|
@@ -187,7 +189,7 @@ splitline(Line *t, int cutpoint)
|
|
187
189
|
* types.
|
188
190
|
*/
|
189
191
|
static void
|
190
|
-
checkline(Line *l,
|
192
|
+
checkline(Line *l, mkd_flag_t flags)
|
191
193
|
{
|
192
194
|
int eol, i;
|
193
195
|
int dashes = 0, spaces = 0,
|
@@ -213,11 +215,11 @@ checkline(Line *l, DWORD flags)
|
|
213
215
|
switch (c) {
|
214
216
|
case '-': UNLESS_FENCED(dashes = 1); break;
|
215
217
|
case ' ': UNLESS_FENCED(spaces = 1); break;
|
216
|
-
case '=': equals = 1; break;
|
218
|
+
case '=': UNLESS_FENCED(equals = 1); break;
|
217
219
|
case '_': UNLESS_FENCED(underscores = 1); break;
|
218
220
|
case '*': stars = 1; break;
|
219
221
|
default:
|
220
|
-
if (flags
|
222
|
+
if ( is_flag_set(flags, MKD_FENCEDCODE) ) {
|
221
223
|
switch (c) {
|
222
224
|
case '~': if (other) return; is_fence_char = 1; tildes = 1; break;
|
223
225
|
case '`': if (other) return; is_fence_char = 1; backticks = 1; break;
|
@@ -379,7 +381,7 @@ iscode(Line *t)
|
|
379
381
|
|
380
382
|
|
381
383
|
static inline int
|
382
|
-
ishr(Line *t,
|
384
|
+
ishr(Line *t, mkd_flag_t flags)
|
383
385
|
{
|
384
386
|
if ( ! (t->flags & CHECKED) )
|
385
387
|
checkline(t, flags);
|
@@ -391,7 +393,7 @@ ishr(Line *t, DWORD flags)
|
|
391
393
|
|
392
394
|
|
393
395
|
static int
|
394
|
-
issetext(Line *t, int *htyp,
|
396
|
+
issetext(Line *t, int *htyp, mkd_flag_t flags)
|
395
397
|
{
|
396
398
|
Line *n;
|
397
399
|
|
@@ -413,7 +415,7 @@ issetext(Line *t, int *htyp, DWORD flags)
|
|
413
415
|
|
414
416
|
|
415
417
|
static int
|
416
|
-
ishdr(Line *t, int *htyp,
|
418
|
+
ishdr(Line *t, int *htyp, mkd_flag_t flags)
|
417
419
|
{
|
418
420
|
/* ANY leading `#`'s make this into an ETX header
|
419
421
|
*/
|
@@ -429,7 +431,7 @@ ishdr(Line *t, int *htyp, DWORD flags)
|
|
429
431
|
|
430
432
|
|
431
433
|
static inline int
|
432
|
-
end_of_block(Line *t,
|
434
|
+
end_of_block(Line *t, mkd_flag_t flags)
|
433
435
|
{
|
434
436
|
int dummy;
|
435
437
|
|
@@ -441,9 +443,9 @@ end_of_block(Line *t, DWORD flags)
|
|
441
443
|
|
442
444
|
|
443
445
|
static Line*
|
444
|
-
is_discount_dt(Line *t, int *clip,
|
446
|
+
is_discount_dt(Line *t, int *clip, mkd_flag_t flags)
|
445
447
|
{
|
446
|
-
if ( !(flags
|
448
|
+
if ( !is_flag_set(flags, MKD_NODLDISCOUNT)
|
447
449
|
&& t
|
448
450
|
&& t->next
|
449
451
|
&& (S(t->text) > 2)
|
@@ -470,9 +472,9 @@ is_extra_dd(Line *t)
|
|
470
472
|
|
471
473
|
|
472
474
|
static Line*
|
473
|
-
is_extra_dt(Line *t, int *clip,
|
475
|
+
is_extra_dt(Line *t, int *clip, mkd_flag_t flags)
|
474
476
|
{
|
475
|
-
if ( flags
|
477
|
+
if ( is_flag_set(flags, MKD_DLEXTRA)
|
476
478
|
&& t
|
477
479
|
&& t->next && S(t->text) && T(t->text)[0] != '='
|
478
480
|
&& T(t->text)[S(t->text)-1] != '=') {
|
@@ -494,7 +496,7 @@ is_extra_dt(Line *t, int *clip, DWORD flags)
|
|
494
496
|
|
495
497
|
|
496
498
|
static Line*
|
497
|
-
isdefinition(Line *t, int *clip, int *kind,
|
499
|
+
isdefinition(Line *t, int *clip, int *kind, mkd_flag_t flags)
|
498
500
|
{
|
499
501
|
Line *ret;
|
500
502
|
|
@@ -508,7 +510,7 @@ isdefinition(Line *t, int *clip, int *kind, DWORD flags)
|
|
508
510
|
|
509
511
|
|
510
512
|
static int
|
511
|
-
islist(Line *t, int *clip,
|
513
|
+
islist(Line *t, int *clip, mkd_flag_t flags, int *list_type)
|
512
514
|
{
|
513
515
|
int i, j;
|
514
516
|
char *q;
|
@@ -516,21 +518,22 @@ islist(Line *t, int *clip, DWORD flags, int *list_type)
|
|
516
518
|
if ( end_of_block(t, flags) )
|
517
519
|
return 0;
|
518
520
|
|
519
|
-
if ( !(flags
|
521
|
+
if ( !(is_flag_set(flags, MKD_NODLIST) || is_flag_set(flags, MKD_STRICT))
|
522
|
+
&& isdefinition(t,clip,list_type,flags) )
|
520
523
|
return DL;
|
521
524
|
|
522
525
|
if ( strchr("*-+", T(t->text)[t->dle]) && isspace(T(t->text)[t->dle+1]) ) {
|
523
526
|
i = nextnonblank(t, t->dle+1);
|
524
527
|
*clip = (i > 4) ? 4 : i;
|
525
528
|
*list_type = UL;
|
526
|
-
return AL;
|
529
|
+
return is_flag_set(flags, MKD_EXPLICITLIST) ? UL : AL;
|
527
530
|
}
|
528
531
|
|
529
532
|
if ( (j = nextblank(t,t->dle)) > t->dle ) {
|
530
533
|
if ( T(t->text)[j-1] == '.' ) {
|
531
534
|
|
532
|
-
if ( !(flags
|
533
|
-
|
535
|
+
if ( !(is_flag_set(flags, MKD_NOALPHALIST) || is_flag_set(flags, MKD_STRICT))
|
536
|
+
&& (j == t->dle + 2)
|
534
537
|
&& isalpha(T(t->text)[t->dle]) ) {
|
535
538
|
j = nextnonblank(t,j);
|
536
539
|
*clip = (j > 4) ? 4 : j;
|
@@ -608,8 +611,7 @@ codeblock(Paragraph *p)
|
|
608
611
|
Line *t = p->text, *r;
|
609
612
|
|
610
613
|
for ( ; t; t = r ) {
|
611
|
-
|
612
|
-
t->dle = mkd_firstnonblank(t);
|
614
|
+
__mkd_trim_line(t,4);
|
613
615
|
|
614
616
|
if ( !( (r = skipempty(t->next)) && iscode(r)) ) {
|
615
617
|
___mkd_freeLineRange(t,r);
|
@@ -622,9 +624,9 @@ codeblock(Paragraph *p)
|
|
622
624
|
|
623
625
|
|
624
626
|
static int
|
625
|
-
iscodefence(Line *r, int size, line_type kind,
|
627
|
+
iscodefence(Line *r, int size, line_type kind, mkd_flag_t flags)
|
626
628
|
{
|
627
|
-
if ( !(flags
|
629
|
+
if ( !is_flag_set(flags, MKD_FENCEDCODE) )
|
628
630
|
return 0;
|
629
631
|
|
630
632
|
if ( !(r->flags & CHECKED) )
|
@@ -636,39 +638,40 @@ iscodefence(Line *r, int size, line_type kind, DWORD flags)
|
|
636
638
|
return (r->kind == chk_tilde || r->kind == chk_backtick) && (r->count >= size);
|
637
639
|
}
|
638
640
|
|
641
|
+
|
639
642
|
static Paragraph *
|
640
|
-
fencedcodeblock(ParagraphRoot *d, Line **ptr,
|
643
|
+
fencedcodeblock(ParagraphRoot *d, Line **ptr, mkd_flag_t flags)
|
641
644
|
{
|
642
645
|
Line *first, *r;
|
643
646
|
Paragraph *ret;
|
644
647
|
|
645
648
|
first = (*ptr);
|
646
|
-
|
649
|
+
|
647
650
|
/* don't allow zero-length code fences
|
648
|
-
|
651
|
+
*/
|
649
652
|
if ( (first->next == 0) || iscodefence(first->next, first->count, 0, flags) )
|
650
653
|
return 0;
|
651
654
|
|
652
655
|
/* find the closing fence, discard the fences,
|
653
|
-
|
654
|
-
|
656
|
+
* return a Paragraph with the contents
|
657
|
+
*/
|
655
658
|
for ( r = first; r && r->next; r = r->next )
|
656
659
|
if ( iscodefence(r->next, first->count, first->kind, flags) ) {
|
657
660
|
(*ptr) = r->next->next;
|
658
661
|
ret = Pp(d, first->next, CODE);
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
}
|
667
|
-
___mkd_freeLine(first);
|
668
|
-
___mkd_freeLine(r->next);
|
669
|
-
r->next = 0;
|
670
|
-
return ret;
|
662
|
+
if (S(first->text) - first->count > 0) {
|
663
|
+
char *lang_attr = T(first->text) + first->count;
|
664
|
+
while ( *lang_attr != 0 && *lang_attr == ' ' ) lang_attr++;
|
665
|
+
ret->lang = strdup(lang_attr);
|
666
|
+
}
|
667
|
+
else {
|
668
|
+
ret->lang = 0;
|
671
669
|
}
|
670
|
+
___mkd_freeLine(first);
|
671
|
+
___mkd_freeLine(r->next);
|
672
|
+
r->next = 0;
|
673
|
+
return ret;
|
674
|
+
}
|
672
675
|
return 0;
|
673
676
|
}
|
674
677
|
|
@@ -692,7 +695,7 @@ centered(Line *first, Line *last)
|
|
692
695
|
|
693
696
|
|
694
697
|
static int
|
695
|
-
endoftextblock(Line *t, int toplevelblock,
|
698
|
+
endoftextblock(Line *t, int toplevelblock, mkd_flag_t flags)
|
696
699
|
{
|
697
700
|
int z;
|
698
701
|
|
@@ -712,7 +715,7 @@ endoftextblock(Line *t, int toplevelblock, DWORD flags)
|
|
712
715
|
|
713
716
|
|
714
717
|
static Line *
|
715
|
-
textblock(Paragraph *p, int toplevel,
|
718
|
+
textblock(Paragraph *p, int toplevel, mkd_flag_t flags)
|
716
719
|
{
|
717
720
|
Line *t, *next;
|
718
721
|
|
@@ -747,12 +750,12 @@ szmarkerclass(char *p)
|
|
747
750
|
#define iscsschar(c) (isalpha(c) || (c == '-') || (c == '_') )
|
748
751
|
|
749
752
|
static int
|
750
|
-
isdivmarker(Line *p, int start,
|
753
|
+
isdivmarker(Line *p, int start, mkd_flag_t flags)
|
751
754
|
{
|
752
755
|
char *s;
|
753
756
|
int last, i;
|
754
757
|
|
755
|
-
if ( flags
|
758
|
+
if ( is_flag_set(flags, MKD_NODIVQUOTE) || is_flag_set(flags, MKD_STRICT) )
|
756
759
|
return 0;
|
757
760
|
|
758
761
|
start = nextnonblank(p, start);
|
@@ -786,7 +789,7 @@ isdivmarker(Line *p, int start, DWORD flags)
|
|
786
789
|
* way the markdown sample web form at Daring Fireball works.
|
787
790
|
*/
|
788
791
|
static Line *
|
789
|
-
quoteblock(Paragraph *p,
|
792
|
+
quoteblock(Paragraph *p, mkd_flag_t flags)
|
790
793
|
{
|
791
794
|
Line *t, *q;
|
792
795
|
int qp;
|
@@ -803,9 +806,8 @@ quoteblock(Paragraph *p, DWORD flags)
|
|
803
806
|
/* clip next space, if any */
|
804
807
|
if ( T(t->text)[qp] == ' ' )
|
805
808
|
qp++;
|
806
|
-
|
809
|
+
__mkd_trim_line(t,qp);
|
807
810
|
UNCHECK(t);
|
808
|
-
t->dle = mkd_firstnonblank(t);
|
809
811
|
}
|
810
812
|
|
811
813
|
q = skipempty(t->next);
|
@@ -847,16 +849,40 @@ typedef int (*linefn)(Line *);
|
|
847
849
|
* marker, but multiple paragraphs need to start with a 4-space indent.
|
848
850
|
*/
|
849
851
|
static Line *
|
850
|
-
listitem(Paragraph *p, int indent,
|
852
|
+
listitem(Paragraph *p, int indent, mkd_flag_t flags, linefn check)
|
851
853
|
{
|
852
854
|
Line *t, *q;
|
853
855
|
int clip = indent;
|
854
856
|
int z;
|
857
|
+
#ifdef GITHUB_CHECKBOX
|
858
|
+
int firstpara = 1;
|
859
|
+
int ischeck;
|
860
|
+
#define CHECK_NOT 0
|
861
|
+
#define CHECK_NO 1
|
862
|
+
#define CHECK_YES 2
|
863
|
+
#endif
|
855
864
|
|
856
865
|
for ( t = p->text; t ; t = q) {
|
857
|
-
CLIP(t->text, 0, clip);
|
858
866
|
UNCHECK(t);
|
859
|
-
t
|
867
|
+
__mkd_trim_line(t, clip);
|
868
|
+
|
869
|
+
#ifdef GITHUB_CHECKBOX
|
870
|
+
if ( firstpara ) {
|
871
|
+
ischeck = CHECK_NOT;
|
872
|
+
if ( strncmp(T(t->text)+t->dle, "[ ]", 3) == 0 )
|
873
|
+
ischeck = CHECK_NO;
|
874
|
+
else if ( strncasecmp(T(t->text)+t->dle, "[x]", 3) == 0 )
|
875
|
+
ischeck = CHECK_YES;
|
876
|
+
|
877
|
+
if ( ischeck != CHECK_NOT ) {
|
878
|
+
__mkd_trim_line(t, 3);
|
879
|
+
p->flags |= GITHUB_CHECK;
|
880
|
+
if ( ischeck == CHECK_YES )
|
881
|
+
p->flags |= IS_CHECKED;
|
882
|
+
}
|
883
|
+
firstpara = 0;
|
884
|
+
}
|
885
|
+
#endif
|
860
886
|
|
861
887
|
/* even though we had to trim a long leader off this item,
|
862
888
|
* the indent for trailing paragraphs is still 4...
|
@@ -1005,6 +1031,28 @@ tgood(char c)
|
|
1005
1031
|
}
|
1006
1032
|
|
1007
1033
|
|
1034
|
+
/*
|
1035
|
+
* eat lines for a markdown extra footnote
|
1036
|
+
*/
|
1037
|
+
static Line *
|
1038
|
+
extrablock(Line *p)
|
1039
|
+
{
|
1040
|
+
Line *np;
|
1041
|
+
|
1042
|
+
while ( p && p->next ) {
|
1043
|
+
np = p->next;
|
1044
|
+
|
1045
|
+
if ( np->dle < 4 && np->dle < S(np->text) ) {
|
1046
|
+
p->next = 0;
|
1047
|
+
return np;
|
1048
|
+
}
|
1049
|
+
__mkd_trim_line(np,4);
|
1050
|
+
p = np;
|
1051
|
+
}
|
1052
|
+
return 0;
|
1053
|
+
}
|
1054
|
+
|
1055
|
+
|
1008
1056
|
/*
|
1009
1057
|
* add a new (image or link) footnote to the footnote table
|
1010
1058
|
*/
|
@@ -1020,20 +1068,31 @@ addfootnote(Line *p, MMIOT* f)
|
|
1020
1068
|
CREATE(foot->tag);
|
1021
1069
|
CREATE(foot->link);
|
1022
1070
|
CREATE(foot->title);
|
1071
|
+
foot->text = 0;
|
1023
1072
|
foot->flags = foot->height = foot->width = 0;
|
1024
1073
|
|
1074
|
+
/* keep the footnote label */
|
1025
1075
|
for (j=i=p->dle+1; T(p->text)[j] != ']'; j++)
|
1026
1076
|
EXPAND(foot->tag) = T(p->text)[j];
|
1027
|
-
|
1028
1077
|
EXPAND(foot->tag) = 0;
|
1029
1078
|
S(foot->tag)--;
|
1079
|
+
|
1080
|
+
/* consume the closing ]: */
|
1030
1081
|
j = nextnonblank(p, j+2);
|
1031
1082
|
|
1032
|
-
if ( (f->flags
|
1033
|
-
/*
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1083
|
+
if ( is_flag_set(f->flags, MKD_EXTRA_FOOTNOTE) && (T(foot->tag)[0] == '^') ) {
|
1084
|
+
/* markdown extra footnote: All indented lines past this point;
|
1085
|
+
* the first line includes the footnote reference, so we need to
|
1086
|
+
* snip that out as we go.
|
1087
|
+
*/
|
1088
|
+
foot->flags |= EXTRA_FOOTNOTE;
|
1089
|
+
__mkd_trim_line(p,j);
|
1090
|
+
|
1091
|
+
np = extrablock(p);
|
1092
|
+
|
1093
|
+
foot->text = compile(p, 0, f);
|
1094
|
+
|
1095
|
+
return np;
|
1037
1096
|
}
|
1038
1097
|
|
1039
1098
|
while ( (j < S(p->text)) && !isspace(T(p->text)[j]) )
|
@@ -1044,8 +1103,7 @@ addfootnote(Line *p, MMIOT* f)
|
|
1044
1103
|
|
1045
1104
|
if ( T(p->text)[j] == '=' ) {
|
1046
1105
|
sscanf(T(p->text)+j, "=%dx%d", &foot->width, &foot->height);
|
1047
|
-
|
1048
|
-
++j;
|
1106
|
+
j = nextblank(p, j);
|
1049
1107
|
j = nextnonblank(p,j);
|
1050
1108
|
}
|
1051
1109
|
|
@@ -1075,7 +1133,6 @@ addfootnote(Line *p, MMIOT* f)
|
|
1075
1133
|
--S(foot->title);
|
1076
1134
|
}
|
1077
1135
|
|
1078
|
-
skip_to_end:
|
1079
1136
|
___mkd_freeLine(p);
|
1080
1137
|
return np;
|
1081
1138
|
}
|
@@ -1113,6 +1170,22 @@ consume(Line *ptr, int *eaten)
|
|
1113
1170
|
}
|
1114
1171
|
|
1115
1172
|
|
1173
|
+
typedef ANCHOR(Line) Cache;
|
1174
|
+
|
1175
|
+
static void
|
1176
|
+
uncache(Cache *cache, ParagraphRoot *d, MMIOT *f)
|
1177
|
+
{
|
1178
|
+
Paragraph *p;
|
1179
|
+
|
1180
|
+
if ( T(*cache) ) {
|
1181
|
+
E(*cache)->next = 0;
|
1182
|
+
p = Pp(d, 0, SOURCE);
|
1183
|
+
p->down = compile(T(*cache), 1, f);
|
1184
|
+
T(*cache) = E(*cache) = 0;
|
1185
|
+
}
|
1186
|
+
}
|
1187
|
+
|
1188
|
+
|
1116
1189
|
/*
|
1117
1190
|
* top-level compilation; break the document into
|
1118
1191
|
* style, html, and source blocks with footnote links
|
@@ -1122,25 +1195,21 @@ static Paragraph *
|
|
1122
1195
|
compile_document(Line *ptr, MMIOT *f)
|
1123
1196
|
{
|
1124
1197
|
ParagraphRoot d = { 0, 0 };
|
1125
|
-
|
1198
|
+
Cache source = { 0, 0 };
|
1126
1199
|
Paragraph *p = 0;
|
1127
1200
|
struct kw *tag;
|
1128
1201
|
int eaten, unclosed;
|
1202
|
+
int previous_was_break = 1;
|
1129
1203
|
|
1130
1204
|
while ( ptr ) {
|
1131
|
-
if ( !(f->flags
|
1205
|
+
if ( !is_flag_set(f->flags, MKD_NOHTML) && (tag = isopentag(ptr)) ) {
|
1132
1206
|
int blocktype;
|
1133
1207
|
/* If we encounter a html/style block, compile and save all
|
1134
1208
|
* of the cached source BEFORE processing the html/style.
|
1135
1209
|
*/
|
1136
|
-
|
1137
|
-
E(source)->next = 0;
|
1138
|
-
p = Pp(&d, 0, SOURCE);
|
1139
|
-
p->down = compile(T(source), 1, f);
|
1140
|
-
T(source) = E(source) = 0;
|
1141
|
-
}
|
1210
|
+
uncache(&source, &d, f);
|
1142
1211
|
|
1143
|
-
if (
|
1212
|
+
if (is_flag_set(f->flags, MKD_NOSTYLE) )
|
1144
1213
|
blocktype = HTML;
|
1145
1214
|
else
|
1146
1215
|
blocktype = strcmp(tag->id, "STYLE") == 0 ? STYLE : HTML;
|
@@ -1151,6 +1220,7 @@ compile_document(Line *ptr, MMIOT *f)
|
|
1151
1220
|
p->down = compile(p->text, 1, f);
|
1152
1221
|
p->text = 0;
|
1153
1222
|
}
|
1223
|
+
previous_was_break = 1;
|
1154
1224
|
}
|
1155
1225
|
else if ( isfootnote(ptr) ) {
|
1156
1226
|
/* footnotes, like cats, sleep anywhere; pull them
|
@@ -1158,23 +1228,27 @@ compile_document(Line *ptr, MMIOT *f)
|
|
1158
1228
|
* later processing
|
1159
1229
|
*/
|
1160
1230
|
ptr = consume(addfootnote(ptr, f), &eaten);
|
1231
|
+
previous_was_break = 1;
|
1232
|
+
}
|
1233
|
+
else if ( previous_was_break && iscodefence(ptr,3,0,f->flags)) {
|
1234
|
+
uncache(&source, &d, f);
|
1235
|
+
if ( !fencedcodeblock(&d, &ptr, f->flags) ) /* just source */
|
1236
|
+
goto attach;
|
1161
1237
|
}
|
1162
1238
|
else {
|
1239
|
+
attach:
|
1163
1240
|
/* source; cache it up to wait for eof or the
|
1164
1241
|
* next html/style block
|
1165
1242
|
*/
|
1166
1243
|
ATTACH(source,ptr);
|
1244
|
+
previous_was_break = blankline(ptr);
|
1167
1245
|
ptr = ptr->next;
|
1168
1246
|
}
|
1169
1247
|
}
|
1170
|
-
if
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
E(source)->next = 0;
|
1175
|
-
p = Pp(&d, 0, SOURCE);
|
1176
|
-
p->down = compile(T(source), 1, f);
|
1177
|
-
}
|
1248
|
+
/* if there's any cached source at EOF, compile
|
1249
|
+
* it now.
|
1250
|
+
*/
|
1251
|
+
uncache(&source, &d, f);
|
1178
1252
|
return T(d);
|
1179
1253
|
}
|
1180
1254
|
|
@@ -1194,7 +1268,7 @@ actually_a_table(MMIOT *f, Line *pp)
|
|
1194
1268
|
int c;
|
1195
1269
|
|
1196
1270
|
/* tables need to be turned on */
|
1197
|
-
if ( f->flags
|
1271
|
+
if ( is_flag_set(f->flags, MKD_STRICT) || is_flag_set(f->flags, MKD_NOTABLES) )
|
1198
1272
|
return 0;
|
1199
1273
|
|
1200
1274
|
/* tables need three lines */
|
@@ -1249,10 +1323,11 @@ compile(Line *ptr, int toplevel, MMIOT *f)
|
|
1249
1323
|
ptr = consume(ptr, ¶);
|
1250
1324
|
|
1251
1325
|
while ( ptr ) {
|
1326
|
+
|
1252
1327
|
if ( iscode(ptr) ) {
|
1253
1328
|
p = Pp(&d, ptr, CODE);
|
1254
1329
|
|
1255
|
-
if ( f->flags
|
1330
|
+
if ( is_flag_set(f->flags, MKD_1_COMPAT) ) {
|
1256
1331
|
/* HORRIBLE STANDARDS KLUDGE: the first line of every block
|
1257
1332
|
* has trailing whitespace trimmed off.
|
1258
1333
|
*/
|
@@ -1290,13 +1365,39 @@ compile(Line *ptr, int toplevel, MMIOT *f)
|
|
1290
1365
|
ptr = headerblock(p, hdr_type);
|
1291
1366
|
}
|
1292
1367
|
else {
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1368
|
+
/* either markup or an html block element
|
1369
|
+
*/
|
1370
|
+
struct kw *tag;
|
1371
|
+
int unclosed = 1;
|
1372
|
+
|
1373
|
+
p = Pp(&d, ptr, MARKUP); /* default to regular markup,
|
1374
|
+
* then check if it's an html
|
1375
|
+
* block. If it IS an html
|
1376
|
+
* block, htmlblock() will
|
1377
|
+
* populate this paragraph &
|
1378
|
+
* all we need to do is reset
|
1379
|
+
* the paragraph type to HTML,
|
1380
|
+
* otherwise the paragraph
|
1381
|
+
* remains empty and ready for
|
1382
|
+
* processing with textblock()
|
1383
|
+
*/
|
1384
|
+
|
1385
|
+
if ( !is_flag_set(f->flags, MKD_NOHTML) && (tag = isopentag(ptr)) ) {
|
1386
|
+
/* possibly an html block
|
1387
|
+
*/
|
1388
|
+
|
1389
|
+
ptr = htmlblock(p, tag, &unclosed);
|
1390
|
+
if ( ! unclosed ) {
|
1391
|
+
p->typ = HTML;
|
1392
|
+
}
|
1393
|
+
}
|
1394
|
+
if ( unclosed ) {
|
1395
|
+
ptr = textblock(p, toplevel, f->flags);
|
1396
|
+
/* tables are a special kind of paragraph */
|
1397
|
+
if ( actually_a_table(f, p->text) )
|
1398
|
+
p->typ = TABLE;
|
1399
|
+
}
|
1298
1400
|
}
|
1299
|
-
|
1300
1401
|
if ( (para||toplevel) && !p->align )
|
1301
1402
|
p->align = PARA;
|
1302
1403
|
|
@@ -1321,7 +1422,7 @@ compile(Line *ptr, int toplevel, MMIOT *f)
|
|
1321
1422
|
* prepare and compile `text`, returning a Paragraph tree.
|
1322
1423
|
*/
|
1323
1424
|
int
|
1324
|
-
mkd_compile(Document *doc,
|
1425
|
+
mkd_compile(Document *doc, mkd_flag_t flags)
|
1325
1426
|
{
|
1326
1427
|
if ( !doc )
|
1327
1428
|
return 0;
|
@@ -1329,9 +1430,10 @@ mkd_compile(Document *doc, DWORD flags)
|
|
1329
1430
|
flags &= USER_FLAGS;
|
1330
1431
|
|
1331
1432
|
if ( doc->compiled ) {
|
1332
|
-
if ( doc->ctx->flags == flags )
|
1433
|
+
if ( doc->ctx->flags == flags && !doc->dirty)
|
1333
1434
|
return 1;
|
1334
1435
|
else {
|
1436
|
+
doc->compiled = doc->dirty = 0;
|
1335
1437
|
if ( doc->code)
|
1336
1438
|
___mkd_freeParagraph(doc->code);
|
1337
1439
|
if ( doc->ctx->footnotes )
|