rdiscount 2.0.7.3 → 2.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,100 @@
1
+
2
+ /*
3
+ * github_flavoured -- implement the obnoxious "returns are hard newlines"
4
+ * feature in github flavoured markdown.
5
+ *
6
+ * Copyright (C) 2012 David L Parsons.
7
+ * The redistribution terms are provided in the COPYRIGHT file that must
8
+ * be distributed with this source code.
9
+ */
10
+ #include "config.h"
11
+ #include <stdio.h>
12
+ #include <stdlib.h>
13
+ #include <ctype.h>
14
+
15
+ #include "cstring.h"
16
+ #include "markdown.h"
17
+ #include "amalloc.h"
18
+
19
+ /* build a Document from any old input.
20
+ */
21
+ typedef int (*getc_func)(void*);
22
+
23
+ Document *
24
+ gfm_populate(getc_func getc, void* ctx, int flags)
25
+ {
26
+ Cstring line;
27
+ Document *a = __mkd_new_Document();
28
+ int c;
29
+ int pandoc = 0;
30
+
31
+ if ( !a ) return 0;
32
+
33
+ a->tabstop = (flags & MKD_TABSTOP) ? 4 : TABSTOP;
34
+
35
+ CREATE(line);
36
+
37
+ while ( (c = (*getc)(ctx)) != EOF ) {
38
+ if ( c == '\n' ) {
39
+ if ( pandoc != EOF && pandoc < 3 ) {
40
+ if ( S(line) && (T(line)[0] == '%') )
41
+ pandoc++;
42
+ else
43
+ pandoc = EOF;
44
+ }
45
+
46
+ if (pandoc == EOF) {
47
+ EXPAND(line) = ' ';
48
+ EXPAND(line) = ' ';
49
+ }
50
+ __mkd_enqueue(a, &line);
51
+ S(line) = 0;
52
+ }
53
+ else if ( isprint(c) || isspace(c) || (c & 0x80) )
54
+ EXPAND(line) = c;
55
+ }
56
+
57
+ if ( S(line) )
58
+ __mkd_enqueue(a, &line);
59
+
60
+ DELETE(line);
61
+
62
+ if ( (pandoc == 3) && !(flags & (MKD_NOHEADER|MKD_STRICT)) ) {
63
+ /* the first three lines started with %, so we have a header.
64
+ * clip the first three lines out of content and hang them
65
+ * off header.
66
+ */
67
+ Line *headers = T(a->content);
68
+
69
+ a->title = headers; __mkd_header_dle(a->title);
70
+ a->author= headers->next; __mkd_header_dle(a->author);
71
+ a->date = headers->next->next; __mkd_header_dle(a->date);
72
+
73
+ T(a->content) = headers->next->next->next;
74
+ }
75
+
76
+ return a;
77
+ }
78
+
79
+
80
+ /* convert a block of text into a linked list
81
+ */
82
+ Document *
83
+ gfm_string(const char *buf, int len, DWORD flags)
84
+ {
85
+ struct string_stream about;
86
+
87
+ about.data = buf;
88
+ about.size = len;
89
+
90
+ return gfm_populate((getc_func)__mkd_io_strget, &about, flags & INPUT_MASK);
91
+ }
92
+
93
+
94
+ /* convert a file into a linked list
95
+ */
96
+ Document *
97
+ gfm_in(FILE *f, DWORD flags)
98
+ {
99
+ return gfm_populate((getc_func)fgetc, f, flags & INPUT_MASK);
100
+ }
data/ext/html5.c CHANGED
@@ -10,8 +10,6 @@ mkd_with_html5_tags()
10
10
  if ( populated ) return;
11
11
  populated = 1;
12
12
 
13
- mkd_prepare_tags();
14
-
15
13
  mkd_define_tag("ASIDE", 0);
16
14
  mkd_define_tag("FOOTER", 0);
17
15
  mkd_define_tag("HEADER", 0);
data/ext/markdown.c CHANGED
@@ -22,6 +22,9 @@ typedef int (*stfu)(const void*,const void*);
22
22
 
23
23
  typedef ANCHOR(Paragraph) ParagraphRoot;
24
24
 
25
+ static Paragraph *Pp(ParagraphRoot *, Line *, int);
26
+ static Paragraph *compile(Line *, int, MMIOT *);
27
+
25
28
  /* case insensitive string sort for Footnote tags.
26
29
  */
27
30
  int
@@ -77,7 +80,7 @@ mkd_firstnonblank(Line *p)
77
80
  }
78
81
 
79
82
 
80
- static int
83
+ static inline int
81
84
  blankline(Line *p)
82
85
  {
83
86
  return ! (p && (S(p->text) > p->dle) );
@@ -173,6 +176,68 @@ splitline(Line *t, int cutpoint)
173
176
  }
174
177
  }
175
178
 
179
+ #define UNCHECK(l) ((l)->flags &= ~CHECKED)
180
+
181
+ /*
182
+ * walk a line, seeing if it's any of half a dozen interesting regular
183
+ * types.
184
+ */
185
+ static void
186
+ checkline(Line *l)
187
+ {
188
+ int eol, i;
189
+ int dashes = 0, spaces = 0,
190
+ equals = 0, underscores = 0,
191
+ stars = 0, tildes = 0,
192
+ backticks = 0;
193
+
194
+ l->flags |= CHECKED;
195
+ l->kind = chk_text;
196
+ l->count = 0;
197
+
198
+ if (l->dle >= 4) { l->kind=chk_code; return; }
199
+
200
+ for ( eol = S(l->text); eol > l->dle && isspace(T(l->text)[eol-1]); --eol )
201
+ ;
202
+
203
+ for (i=l->dle; i<eol; i++) {
204
+ register int c = T(l->text)[i];
205
+
206
+ if ( c != ' ' ) l->count++;
207
+
208
+ switch (c) {
209
+ case '-': dashes = 1; break;
210
+ case ' ': spaces = 1; break;
211
+ case '=': equals = 1; break;
212
+ case '_': underscores = 1; break;
213
+ case '*': stars = 1; break;
214
+ #if WITH_FENCED_CODE
215
+ case '~': tildes = 1; break;
216
+ case '`': backticks = 1; break;
217
+ #endif
218
+ default: return;
219
+ }
220
+ }
221
+
222
+ if ( dashes + equals + underscores + stars + tildes + backticks > 1 )
223
+ return;
224
+
225
+ if ( spaces ) {
226
+ if ( (underscores || stars || dashes) )
227
+ l->kind = chk_hr;
228
+ return;
229
+ }
230
+
231
+ if ( stars || underscores ) { l->kind = chk_hr; }
232
+ else if ( dashes ) { l->kind = chk_dash; }
233
+ else if ( equals ) { l->kind = chk_equal; }
234
+ #if WITH_FENCED_CODE
235
+ else if ( tildes ) { l->kind = chk_tilde; }
236
+ else if ( backticks ) { l->kind = chk_backtick; }
237
+ #endif
238
+ }
239
+
240
+
176
241
 
177
242
  static Line *
178
243
  commentblock(Paragraph *p, int *unclosed)
@@ -261,37 +326,6 @@ htmlblock(Paragraph *p, struct kw *tag, int *unclosed)
261
326
  }
262
327
 
263
328
 
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
-
295
329
  /* footnotes look like ^<whitespace>{0,3}[stuff]: <content>$
296
330
  */
297
331
  static int
@@ -312,76 +346,46 @@ isfootnote(Line *t)
312
346
  }
313
347
 
314
348
 
315
- static int
349
+ static inline int
316
350
  isquote(Line *t)
317
351
  {
318
- int j;
319
-
320
- for ( j=0; j < 4; j++ )
321
- if ( T(t->text)[j] == '>' )
322
- return 1;
323
- else if ( !isspace(T(t->text)[j]) )
324
- return 0;
325
- return 0;
352
+ return (t->dle < 4 && T(t->text)[t->dle] == '>');
326
353
  }
327
354
 
328
355
 
329
- static int
330
- dashchar(char c)
331
- {
332
- return (c == '*') || (c == '-') || (c == '_');
333
- }
334
-
335
-
336
- static int
356
+ static inline int
337
357
  iscode(Line *t)
338
358
  {
339
359
  return (t->dle >= 4);
340
360
  }
341
361
 
342
362
 
343
- static int
363
+ static inline int
344
364
  ishr(Line *t)
345
365
  {
346
- int i, count=0;
347
- char dash = 0;
348
- char c;
349
-
350
- if ( iscode(t) ) return 0;
351
-
352
- for ( i = 0; i < S(t->text); i++) {
353
- c = T(t->text)[i];
354
- if ( (dash == 0) && dashchar(c) )
355
- dash = c;
366
+ if ( ! (t->flags & CHECKED) )
367
+ checkline(t);
356
368
 
357
- if ( c == dash ) ++count;
358
- else if ( !isspace(c) )
359
- return 0;
360
- }
361
- return (count >= 3);
369
+ if ( t->count > 2 )
370
+ return t->kind == chk_hr || t->kind == chk_dash || t->kind == chk_equal;
371
+ return 0;
362
372
  }
363
373
 
364
374
 
365
375
  static int
366
376
  issetext(Line *t, int *htyp)
367
377
  {
368
- int i;
369
- /* then check for setext-style HEADER
370
- * ======
378
+ Line *n;
379
+
380
+ /* check for setext-style HEADER
381
+ * ======
371
382
  */
372
383
 
373
- if ( t->next ) {
374
- char *q = T(t->next->text);
375
- int last = S(t->next->text);
376
-
377
- if ( (*q == '=') || (*q == '-') ) {
378
- /* ignore trailing whitespace */
379
- while ( (last > 1) && isspace(q[last-1]) )
380
- --last;
384
+ if ( (n = t->next) ) {
385
+ if ( !(n->flags & CHECKED) )
386
+ checkline(n);
381
387
 
382
- for (i=1; i < last; i++)
383
- if ( q[0] != q[i] )
384
- return 0;
388
+ if ( n->kind == chk_dash || n->kind == chk_equal ) {
385
389
  *htyp = SETEXT;
386
390
  return 1;
387
391
  }
@@ -393,28 +397,31 @@ issetext(Line *t, int *htyp)
393
397
  static int
394
398
  ishdr(Line *t, int *htyp)
395
399
  {
396
- int i;
397
-
398
-
399
- /* first check for etx-style ###HEADER###
400
- */
401
-
402
- /* leading run of `#`'s ?
403
- */
404
- for ( i=0; T(t->text)[i] == '#'; ++i)
405
- ;
406
-
407
400
  /* ANY leading `#`'s make this into an ETX header
408
401
  */
409
- if ( i && (i < S(t->text) || i > 1) ) {
402
+ if ( (t->dle == 0) && (S(t->text) > 1) && (T(t->text)[0] == '#') ) {
410
403
  *htyp = ETX;
411
404
  return 1;
412
405
  }
413
406
 
407
+ /* And if not, maybe it's a SETEXT header instead
408
+ */
414
409
  return issetext(t, htyp);
415
410
  }
416
411
 
417
412
 
413
+ static inline int
414
+ end_of_block(Line *t)
415
+ {
416
+ int dummy;
417
+
418
+ if ( !t )
419
+ return 0;
420
+
421
+ return ( (S(t->text) <= t->dle) || ishr(t) || ishdr(t, &dummy) );
422
+ }
423
+
424
+
418
425
  static Line*
419
426
  is_discount_dt(Line *t, int *clip)
420
427
  {
@@ -448,13 +455,12 @@ static Line*
448
455
  is_extra_dt(Line *t, int *clip)
449
456
  {
450
457
  #if USE_EXTRA_DL
451
- int i;
452
458
 
453
- if ( t && t->next && T(t->text)[0] != '='
459
+ if ( t && t->next && S(t->text) && T(t->text)[0] != '='
454
460
  && T(t->text)[S(t->text)-1] != '=') {
455
461
  Line *x;
456
462
 
457
- if ( iscode(t) || blankline(t) || ishdr(t,&i) || ishr(t) )
463
+ if ( iscode(t) || end_of_block(t) )
458
464
  return 0;
459
465
 
460
466
  if ( (x = skipempty(t->next)) && is_extra_dd(x) ) {
@@ -490,7 +496,7 @@ islist(Line *t, int *clip, DWORD flags, int *list_type)
490
496
  int i, j;
491
497
  char *q;
492
498
 
493
- if ( /*iscode(t) ||*/ blankline(t) || ishdr(t,&i) || ishr(t) )
499
+ if ( end_of_block(t) )
494
500
  return 0;
495
501
 
496
502
  if ( !(flags & (MKD_NODLIST|MKD_STRICT)) && isdefinition(t,clip,list_type) )
@@ -518,6 +524,7 @@ islist(Line *t, int *clip, DWORD flags, int *list_type)
518
524
  strtoul(T(t->text)+t->dle, &q, 10);
519
525
  if ( (q > T(t->text)+t->dle) && (q == T(t->text) + (j-1)) ) {
520
526
  j = nextnonblank(t,j);
527
+ /* *clip = j; */
521
528
  *clip = (j > 4) ? 4 : j;
522
529
  *list_type = OL;
523
530
  return AL;
@@ -561,6 +568,7 @@ headerblock(Paragraph *pp, int htyp)
561
568
  ++i;
562
569
 
563
570
  CLIP(p->text, 0, i);
571
+ UNCHECK(p);
564
572
 
565
573
  for (j=S(p->text); (j > 1) && (T(p->text)[j-1] == '#'); --j)
566
574
  ;
@@ -597,6 +605,49 @@ codeblock(Paragraph *p)
597
605
  }
598
606
 
599
607
 
608
+ #ifdef WITH_FENCED_CODE
609
+ static int
610
+ iscodefence(Line *r, int size, line_type kind)
611
+ {
612
+ if ( !(r->flags & CHECKED) )
613
+ checkline(r);
614
+
615
+ if ( kind )
616
+ return (r->kind == kind) && (r->count >= size);
617
+ else
618
+ return (r->kind == chk_tilde || r->kind == chk_backtick) && (r->count >= size);
619
+ }
620
+
621
+ static Paragraph *
622
+ fencedcodeblock(ParagraphRoot *d, Line **ptr)
623
+ {
624
+ Line *first, *r;
625
+ Paragraph *ret;
626
+
627
+ first = (*ptr);
628
+
629
+ /* don't allow zero-length code fences
630
+ */
631
+ if ( (first->next == 0) || iscodefence(first->next, first->count, 0) )
632
+ return 0;
633
+
634
+ /* find the closing fence, discard the fences,
635
+ * return a Paragraph with the contents
636
+ */
637
+ for ( r = first; r && r->next; r = r->next )
638
+ if ( iscodefence(r->next, first->count, first->kind) ) {
639
+ (*ptr) = r->next->next;
640
+ ret = Pp(d, first->next, CODE);
641
+ ___mkd_freeLine(first);
642
+ ___mkd_freeLine(r->next);
643
+ r->next = 0;
644
+ return ret;
645
+ }
646
+ return 0;
647
+ }
648
+ #endif
649
+
650
+
600
651
  static int
601
652
  centered(Line *first, Line *last)
602
653
  {
@@ -620,19 +671,18 @@ endoftextblock(Line *t, int toplevelblock, DWORD flags)
620
671
  {
621
672
  int z;
622
673
 
623
- if ( blankline(t)||isquote(t)||ishdr(t,&z)||ishr(t) )
674
+ if ( end_of_block(t) || isquote(t) )
624
675
  return 1;
625
676
 
626
- /* HORRIBLE STANDARDS KLUDGE: non-toplevel paragraphs absorb adjacent
627
- * code blocks
677
+ /* HORRIBLE STANDARDS KLUDGES:
678
+ * 1. non-toplevel paragraphs absorb adjacent code blocks
679
+ * 2. Toplevel paragraphs eat absorb adjacent list items,
680
+ * but sublevel blocks behave properly.
681
+ * (What this means is that we only need to check for code
682
+ * blocks at toplevel, and only check for list items at
683
+ * nested levels.)
628
684
  */
629
- if ( toplevelblock && iscode(t) )
630
- return 1;
631
-
632
- /* HORRIBLE STANDARDS KLUDGE: Toplevel paragraphs eat absorb adjacent
633
- * list items, but sublevel blocks behave properly.
634
- */
635
- return toplevelblock ? 0 : islist(t,&z,flags, &z);
685
+ return toplevelblock ? 0 : islist(t,&z,flags,&z);
636
686
  }
637
687
 
638
688
 
@@ -680,6 +730,7 @@ isdivmarker(Line *p, int start, DWORD flags)
680
730
  if ( flags & (MKD_NODIVQUOTE|MKD_STRICT) )
681
731
  return 0;
682
732
 
733
+ start = nextnonblank(p, start);
683
734
  last= S(p->text) - (1 + start);
684
735
  s = T(p->text) + start;
685
736
 
@@ -703,7 +754,7 @@ isdivmarker(Line *p, int start, DWORD flags)
703
754
  *
704
755
  * one sick horrible thing about blockquotes is that even though
705
756
  * it just takes ^> to start a quote, following lines, if quoted,
706
- * assume that the prefix is ``>''. This means that code needs
757
+ * assume that the prefix is ``> ''. This means that code needs
707
758
  * to be indented *5* spaces from the leading '>', but *4* spaces
708
759
  * from the start of the line. This does not appear to be
709
760
  * documented in the reference implementation, but it's the
@@ -728,6 +779,7 @@ quoteblock(Paragraph *p, DWORD flags)
728
779
  if ( T(t->text)[qp] == ' ' )
729
780
  qp++;
730
781
  CLIP(t->text, 0, qp);
782
+ UNCHECK(t);
731
783
  t->dle = mkd_firstnonblank(t);
732
784
  }
733
785
 
@@ -760,28 +812,6 @@ quoteblock(Paragraph *p, DWORD flags)
760
812
  }
761
813
 
762
814
 
763
- /*
764
- * A table block starts with a table header (see istable()), and continues
765
- * until EOF or a line that /doesn't/ contain a |.
766
- */
767
- static Line *
768
- tableblock(Paragraph *p)
769
- {
770
- Line *t, *q;
771
-
772
- for ( t = p->text; t && (q = t->next); t = t->next ) {
773
- if ( !memchr(T(q->text), '|', S(q->text)) ) {
774
- t->next = 0;
775
- return q;
776
- }
777
- }
778
- return 0;
779
- }
780
-
781
-
782
- static Paragraph *Pp(ParagraphRoot *, Line *, int);
783
- static Paragraph *compile(Line *, int, MMIOT *);
784
-
785
815
  typedef int (*linefn)(Line *);
786
816
 
787
817
 
@@ -800,6 +830,7 @@ listitem(Paragraph *p, int indent, DWORD flags, linefn check)
800
830
 
801
831
  for ( t = p->text; t ; t = q) {
802
832
  CLIP(t->text, 0, clip);
833
+ UNCHECK(t);
803
834
  t->dle = mkd_firstnonblank(t);
804
835
 
805
836
  if ( (q = skipempty(t->next)) == 0 ) {
@@ -853,13 +884,14 @@ definition_block(Paragraph *top, int clip, MMIOT *f, int kind)
853
884
  if ( (text = skipempty(q->next)) == 0 )
854
885
  break;
855
886
 
856
- if (( para = (text != q->next) ))
887
+ if ( para = (text != q->next) )
857
888
  ___mkd_freeLineRange(q, text);
858
889
 
859
890
  q->next = 0;
860
891
  if ( kind == 1 /* discount dl */ )
861
892
  for ( q = labels; q; q = q->next ) {
862
893
  CLIP(q->text, 0, 1);
894
+ UNCHECK(q);
863
895
  S(q->text)--;
864
896
  }
865
897
 
@@ -875,7 +907,7 @@ definition_block(Paragraph *top, int clip, MMIOT *f, int kind)
875
907
  if ( (q = skipempty(text)) == 0 )
876
908
  break;
877
909
 
878
- if (( para = (q != text) )) {
910
+ if ( para = (q != text) ) {
879
911
  Line anchor;
880
912
 
881
913
  anchor.next = text;
@@ -1065,6 +1097,7 @@ compile_document(Line *ptr, MMIOT *f)
1065
1097
 
1066
1098
  while ( ptr ) {
1067
1099
  if ( !(f->flags & MKD_NOHTML) && (tag = isopentag(ptr)) ) {
1100
+ int blocktype;
1068
1101
  /* If we encounter a html/style block, compile and save all
1069
1102
  * of the cached source BEFORE processing the html/style.
1070
1103
  */
@@ -1074,7 +1107,12 @@ compile_document(Line *ptr, MMIOT *f)
1074
1107
  p->down = compile(T(source), 1, f);
1075
1108
  T(source) = E(source) = 0;
1076
1109
  }
1077
- p = Pp(&d, ptr, strcmp(tag->id, "STYLE") == 0 ? STYLE : HTML);
1110
+
1111
+ if ( f->flags & MKD_NOSTYLE )
1112
+ blocktype = HTML;
1113
+ else
1114
+ blocktype = strcmp(tag->id, "STYLE") == 0 ? STYLE : HTML;
1115
+ p = Pp(&d, ptr, blocktype);
1078
1116
  ptr = htmlblock(p, tag, &unclosed);
1079
1117
  if ( unclosed ) {
1080
1118
  p->typ = SOURCE;
@@ -1109,6 +1147,58 @@ compile_document(Line *ptr, MMIOT *f)
1109
1147
  }
1110
1148
 
1111
1149
 
1150
+ static int
1151
+ first_nonblank_before(Line *j, int dle)
1152
+ {
1153
+ return (j->dle < dle) ? j->dle : dle;
1154
+ }
1155
+
1156
+
1157
+ static int
1158
+ actually_a_table(MMIOT *f, Line *pp)
1159
+ {
1160
+ Line *r;
1161
+ int j;
1162
+ int c;
1163
+
1164
+ /* tables need to be turned on */
1165
+ if ( f->flags & (MKD_STRICT|MKD_NOTABLES) )
1166
+ return 0;
1167
+
1168
+ /* tables need three lines */
1169
+ if ( !(pp && pp->next && pp->next->next) ) {
1170
+ return 0;
1171
+ }
1172
+
1173
+ /* all lines must contain |'s */
1174
+ for (r = pp; r; r = r->next )
1175
+ if ( !(r->flags & PIPECHAR) ) {
1176
+ return 0;
1177
+ }
1178
+
1179
+ /* if the header has a leading |, all lines must have leading |'s */
1180
+ if ( T(pp->text)[pp->dle] == '|' ) {
1181
+ for ( r = pp; r; r = r->next )
1182
+ if ( T(r->text)[first_nonblank_before(r,pp->dle)] != '|' ) {
1183
+ return 0;
1184
+ }
1185
+ }
1186
+
1187
+ /* second line must be only whitespace, -, |, or : */
1188
+ r = pp->next;
1189
+
1190
+ for ( j=r->dle; j < S(r->text); ++j ) {
1191
+ c = T(r->text)[j];
1192
+
1193
+ if ( !(isspace(c)||(c=='-')||(c==':')||(c=='|')) ) {
1194
+ return 0;
1195
+ }
1196
+ }
1197
+
1198
+ return 1;
1199
+ }
1200
+
1201
+
1112
1202
  /*
1113
1203
  * break a collection of markdown input into
1114
1204
  * blocks of lists, code, html, and text to
@@ -1139,13 +1229,17 @@ compile(Line *ptr, int toplevel, MMIOT *f)
1139
1229
 
1140
1230
  ptr = codeblock(p);
1141
1231
  }
1232
+ #if WITH_FENCED_CODE
1233
+ else if ( iscodefence(ptr,3,0) && (p=fencedcodeblock(&d, &ptr)) )
1234
+ /* yay, it's already done */ ;
1235
+ #endif
1142
1236
  else if ( ishr(ptr) ) {
1143
1237
  p = Pp(&d, 0, HR);
1144
1238
  r = ptr;
1145
1239
  ptr = ptr->next;
1146
1240
  ___mkd_freeLine(r);
1147
1241
  }
1148
- else if (( list_class = islist(ptr, &indent, f->flags, &list_type) )) {
1242
+ else if ( list_class = islist(ptr, &indent, f->flags, &list_type) ) {
1149
1243
  if ( list_class == DL ) {
1150
1244
  p = Pp(&d, ptr, DL);
1151
1245
  ptr = definition_block(p, indent, f, list_type);
@@ -1165,13 +1259,12 @@ compile(Line *ptr, int toplevel, MMIOT *f)
1165
1259
  p = Pp(&d, ptr, HDR);
1166
1260
  ptr = headerblock(p, hdr_type);
1167
1261
  }
1168
- else if ( istable(ptr) && !(f->flags & (MKD_STRICT|MKD_NOTABLES)) ) {
1169
- p = Pp(&d, ptr, TABLE);
1170
- ptr = tableblock(p);
1171
- }
1172
1262
  else {
1173
1263
  p = Pp(&d, ptr, MARKUP);
1174
1264
  ptr = textblock(p, toplevel, f->flags);
1265
+ /* tables are a special kind of paragraph */
1266
+ if ( actually_a_table(f, p->text) )
1267
+ p->typ = TABLE;
1175
1268
  }
1176
1269
 
1177
1270
  if ( (para||toplevel) && !p->align )