rdiscount 2.2.0.1 → 2.2.7
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.
- checksums.yaml +5 -5
- 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 +25 -22
- 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 +14 -10
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 )
|