rdiscount 1.6.8 → 2.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -175,7 +175,7 @@ splitline(Line *t, int cutpoint)
175
175
 
176
176
 
177
177
  static Line *
178
- commentblock(Paragraph *p)
178
+ commentblock(Paragraph *p, int *unclosed)
179
179
  {
180
180
  Line *t, *ret;
181
181
  char *end;
@@ -188,21 +188,24 @@ commentblock(Paragraph *p)
188
188
  return ret;
189
189
  }
190
190
  }
191
+ *unclosed = 1;
191
192
  return t;
192
193
 
193
194
  }
194
195
 
195
196
 
196
197
  static Line *
197
- htmlblock(Paragraph *p, struct kw *tag)
198
+ htmlblock(Paragraph *p, struct kw *tag, int *unclosed)
198
199
  {
199
200
  Line *ret;
200
201
  FLO f = { p->text, 0 };
201
202
  int c;
202
203
  int i, closing, depth=0;
203
204
 
205
+ *unclosed = 0;
206
+
204
207
  if ( tag == &comment )
205
- return commentblock(p);
208
+ return commentblock(p, unclosed);
206
209
 
207
210
  if ( tag->selfclose ) {
208
211
  ret = f.t->next;
@@ -240,6 +243,8 @@ htmlblock(Paragraph *p, struct kw *tag)
240
243
  /* consume trailing gunk in close tag */
241
244
  c = flogetc(&f);
242
245
  }
246
+ if ( c == EOF )
247
+ break;
243
248
  if ( !f.t )
244
249
  return 0;
245
250
  splitline(f.t, floindex(f));
@@ -251,6 +256,7 @@ htmlblock(Paragraph *p, struct kw *tag)
251
256
  }
252
257
  }
253
258
  }
259
+ *unclosed = 1;
254
260
  return 0;
255
261
  }
256
262
 
@@ -409,56 +415,112 @@ ishdr(Line *t, int *htyp)
409
415
  }
410
416
 
411
417
 
412
- static int
413
- isdefinition(Line *t)
418
+ static Line*
419
+ is_discount_dt(Line *t, int *clip)
414
420
  {
415
- #if DL_TAG_EXTENSION
416
- return t && t->next
417
- && (S(t->text) > 2)
418
- && (t->dle == 0)
419
- && (T(t->text)[0] == '=')
420
- && (T(t->text)[S(t->text)-1] == '=')
421
- && ( (t->next->dle >= 4) || isdefinition(t->next) );
422
- #else
421
+ #if USE_DISCOUNT_DL
422
+ if ( t && t->next
423
+ && (S(t->text) > 2)
424
+ && (t->dle == 0)
425
+ && (T(t->text)[0] == '=')
426
+ && (T(t->text)[S(t->text)-1] == '=') ) {
427
+ if ( t->next->dle >= 4 ) {
428
+ *clip = 4;
429
+ return t;
430
+ }
431
+ else
432
+ return is_discount_dt(t->next, clip);
433
+ }
434
+ #endif
423
435
  return 0;
436
+ }
437
+
438
+
439
+ static int
440
+ is_extra_dd(Line *t)
441
+ {
442
+ return (t->dle < 4) && (T(t->text)[t->dle] == ':')
443
+ && isspace(T(t->text)[t->dle+1]);
444
+ }
445
+
446
+
447
+ static Line*
448
+ is_extra_dt(Line *t, int *clip)
449
+ {
450
+ #if USE_EXTRA_DL
451
+ int i;
452
+
453
+ if ( t && t->next && T(t->text)[0] != '='
454
+ && T(t->text)[S(t->text)-1] != '=') {
455
+ Line *x;
456
+
457
+ if ( iscode(t) || blankline(t) || ishdr(t,&i) || ishr(t) )
458
+ return 0;
459
+
460
+ if ( (x = skipempty(t->next)) && is_extra_dd(x) ) {
461
+ *clip = x->dle+2;
462
+ return t;
463
+ }
464
+
465
+ if ( x=is_extra_dt(t->next, clip) )
466
+ return x;
467
+ }
424
468
  #endif
469
+ return 0;
470
+ }
471
+
472
+
473
+ static Line*
474
+ isdefinition(Line *t, int *clip, int *kind)
475
+ {
476
+ Line *ret;
477
+
478
+ *kind = 1;
479
+ if ( ret = is_discount_dt(t,clip) )
480
+ return ret;
481
+
482
+ *kind=2;
483
+ return is_extra_dt(t,clip);
425
484
  }
426
485
 
427
486
 
428
487
  static int
429
- islist(Line *t, int *trim)
488
+ islist(Line *t, int *clip, DWORD flags, int *list_type)
430
489
  {
431
490
  int i, j;
432
491
  char *q;
433
492
 
434
- if ( iscode(t) || blankline(t) || ishdr(t,&i) || ishr(t) )
493
+ if ( /*iscode(t) ||*/ blankline(t) || ishdr(t,&i) || ishr(t) )
435
494
  return 0;
436
495
 
437
- if ( isdefinition(t) ) {
438
- *trim = 4;
496
+ if ( !(flags & (MKD_NODLIST|MKD_STRICT)) && isdefinition(t,clip,list_type) )
439
497
  return DL;
440
- }
441
498
 
442
499
  if ( strchr("*-+", T(t->text)[t->dle]) && isspace(T(t->text)[t->dle+1]) ) {
443
500
  i = nextnonblank(t, t->dle+1);
444
- *trim = (i > 4) ? 4 : i;
445
- return UL;
501
+ *clip = (i > 4) ? 4 : i;
502
+ *list_type = UL;
503
+ return AL;
446
504
  }
447
505
 
448
506
  if ( (j = nextblank(t,t->dle)) > t->dle ) {
449
507
  if ( T(t->text)[j-1] == '.' ) {
450
- #if ALPHA_LIST
451
- if ( (j == t->dle + 2) && isalpha(T(t->text)[t->dle]) ) {
452
- j = nextnonblank(t,j);
453
- *trim = j;
454
- return AL;
455
- }
456
- #endif
508
+
509
+ if ( !(flags & (MKD_NOALPHALIST|MKD_STRICT))
510
+ && (j == t->dle + 2)
511
+ && isalpha(T(t->text)[t->dle]) ) {
512
+ j = nextnonblank(t,j);
513
+ *clip = (j > 4) ? 4 : j;
514
+ *list_type = AL;
515
+ return AL;
516
+ }
517
+
457
518
  strtoul(T(t->text)+t->dle, &q, 10);
458
519
  if ( (q > T(t->text)+t->dle) && (q == T(t->text) + (j-1)) ) {
459
520
  j = nextnonblank(t,j);
460
- *trim = j;
461
- return OL;
521
+ *clip = (j > 4) ? 4 : j;
522
+ *list_type = OL;
523
+ return AL;
462
524
  }
463
525
  }
464
526
  }
@@ -554,27 +616,33 @@ centered(Line *first, Line *last)
554
616
 
555
617
 
556
618
  static int
557
- endoftextblock(Line *t, int toplevelblock)
619
+ endoftextblock(Line *t, int toplevelblock, DWORD flags)
558
620
  {
559
621
  int z;
560
622
 
561
- if ( blankline(t)||isquote(t)||iscode(t)||ishdr(t,&z)||ishr(t) )
623
+ if ( blankline(t)||isquote(t)||ishdr(t,&z)||ishr(t) )
624
+ return 1;
625
+
626
+ /* HORRIBLE STANDARDS KLUDGE: non-toplevel paragraphs absorb adjacent
627
+ * code blocks
628
+ */
629
+ if ( toplevelblock && iscode(t) )
562
630
  return 1;
563
631
 
564
632
  /* HORRIBLE STANDARDS KLUDGE: Toplevel paragraphs eat absorb adjacent
565
633
  * list items, but sublevel blocks behave properly.
566
634
  */
567
- return toplevelblock ? 0 : islist(t,&z);
635
+ return toplevelblock ? 0 : islist(t,&z,flags, &z);
568
636
  }
569
637
 
570
638
 
571
639
  static Line *
572
- textblock(Paragraph *p, int toplevel)
640
+ textblock(Paragraph *p, int toplevel, DWORD flags)
573
641
  {
574
642
  Line *t, *next;
575
643
 
576
644
  for ( t = p->text; t ; t = next ) {
577
- if ( ((next = t->next) == 0) || endoftextblock(next, toplevel) ) {
645
+ if ( ((next = t->next) == 0) || endoftextblock(next, toplevel, flags) ) {
578
646
  p->align = centered(p->text, t);
579
647
  t->next = 0;
580
648
  return next;
@@ -601,27 +669,32 @@ szmarkerclass(char *p)
601
669
  * check if the first line of a quoted block is the special div-not-quote
602
670
  * marker %[kind:]name%
603
671
  */
672
+ #define iscsschar(c) (isalpha(c) || (c == '-') || (c == '_') )
673
+
604
674
  static int
605
- isdivmarker(Line *p, int start)
675
+ isdivmarker(Line *p, int start, DWORD flags)
606
676
  {
607
- #if DIV_QUOTE
608
- char *s = T(p->text);
609
- int len = S(p->text);
610
- int i;
677
+ char *s;
678
+ int last, i;
611
679
 
612
- if ( !(len && s[start] == '%' && s[len-1] == '%') ) return 0;
680
+ if ( flags & (MKD_NODIVQUOTE|MKD_STRICT) )
681
+ return 0;
682
+
683
+ last= S(p->text) - (1 + start);
684
+ s = T(p->text) + start;
685
+
686
+ if ( (last <= 0) || (*s != '%') || (s[last] != '%') )
687
+ return 0;
613
688
 
614
- i = szmarkerclass(s+start+1)+start;
615
- len -= start+1;
689
+ i = szmarkerclass(s+1);
616
690
 
617
- while ( ++i < len )
618
- if ( !isalnum(s[i]) )
691
+ if ( !iscsschar(s[i+1]) )
692
+ return 0;
693
+ while ( ++i < last )
694
+ if ( !(isdigit(s[i]) || iscsschar(s[i])) )
619
695
  return 0;
620
696
 
621
697
  return 1;
622
- #else
623
- return 0;
624
- #endif
625
698
  }
626
699
 
627
700
 
@@ -637,7 +710,7 @@ isdivmarker(Line *p, int start)
637
710
  * way the markdown sample web form at Daring Fireball works.
638
711
  */
639
712
  static Line *
640
- quoteblock(Paragraph *p)
713
+ quoteblock(Paragraph *p, DWORD flags)
641
714
  {
642
715
  Line *t, *q;
643
716
  int qp;
@@ -660,13 +733,13 @@ quoteblock(Paragraph *p)
660
733
 
661
734
  q = skipempty(t->next);
662
735
 
663
- if ( (q == 0) || ((q != t->next) && (!isquote(q) || isdivmarker(q,1))) ) {
736
+ if ( (q == 0) || ((q != t->next) && (!isquote(q) || isdivmarker(q,1,flags))) ) {
664
737
  ___mkd_freeLineRange(t, q);
665
738
  t = q;
666
739
  break;
667
740
  }
668
741
  }
669
- if ( isdivmarker(p->text,0) ) {
742
+ if ( isdivmarker(p->text,0,flags) ) {
670
743
  char *prefix = "class";
671
744
  int i;
672
745
 
@@ -709,6 +782,8 @@ tableblock(Paragraph *p)
709
782
  static Paragraph *Pp(ParagraphRoot *, Line *, int);
710
783
  static Paragraph *compile(Line *, int, MMIOT *);
711
784
 
785
+ typedef int (*linefn)(Line *);
786
+
712
787
 
713
788
  /*
714
789
  * pull in a list block. A list block starts with a list marker and
@@ -717,7 +792,7 @@ static Paragraph *compile(Line *, int, MMIOT *);
717
792
  * marker, but multiple paragraphs need to start with a 4-space indent.
718
793
  */
719
794
  static Line *
720
- listitem(Paragraph *p, int indent)
795
+ listitem(Paragraph *p, int indent, DWORD flags, linefn check)
721
796
  {
722
797
  Line *t, *q;
723
798
  int clip = indent;
@@ -748,7 +823,9 @@ listitem(Paragraph *p, int indent)
748
823
  indent = clip ? clip : 2;
749
824
  }
750
825
 
751
- if ( (q->dle < indent) && (ishr(q) || islist(q,&z)) && !issetext(q,&z) ) {
826
+ if ( (q->dle < indent) && (ishr(q) || islist(q,&z,flags,&z)
827
+ || (check && (*check)(q)))
828
+ && !issetext(q,&z) ) {
752
829
  q = t->next;
753
830
  t->next = 0;
754
831
  return q;
@@ -761,39 +838,81 @@ listitem(Paragraph *p, int indent)
761
838
 
762
839
 
763
840
  static Line *
764
- listblock(Paragraph *top, int trim, MMIOT *f)
841
+ definition_block(Paragraph *top, int clip, MMIOT *f, int kind)
765
842
  {
766
843
  ParagraphRoot d = { 0, 0 };
767
844
  Paragraph *p;
768
- Line *q = top->text, *text, *label;
769
- int isdl = (top->typ == DL),
770
- para = 0,
771
- ltype;
845
+ Line *q = top->text, *text = 0, *labels;
846
+ int z, para;
772
847
 
773
- while (( text = q )) {
774
- if ( top->typ == DL ) {
775
- Line *lp;
776
-
777
- for ( lp = label = text; lp ; lp = lp->next ) {
778
- text = lp->next;
779
- CLIP(lp->text, 0, 1);
780
- S(lp->text)--;
781
- if ( !isdefinition(lp->next) )
782
- lp->next = 0;
848
+ while (( labels = q )) {
849
+
850
+ if ( (q = isdefinition(labels, &z, &kind)) == 0 )
851
+ break;
852
+
853
+ if ( (text = skipempty(q->next)) == 0 )
854
+ break;
855
+
856
+ if (( para = (text != q->next) ))
857
+ ___mkd_freeLineRange(q, text);
858
+
859
+ q->next = 0;
860
+ if ( kind == 1 /* discount dl */ )
861
+ for ( q = labels; q; q = q->next ) {
862
+ CLIP(q->text, 0, 1);
863
+ S(q->text)--;
783
864
  }
865
+
866
+ dd_block:
867
+ p = Pp(&d, text, LISTITEM);
868
+
869
+ text = listitem(p, clip, f->flags, (kind==2) ? is_extra_dd : 0);
870
+ p->down = compile(p->text, 0, f);
871
+ p->text = labels; labels = 0;
872
+
873
+ if ( para && p->down ) p->down->align = PARA;
874
+
875
+ if ( (q = skipempty(text)) == 0 )
876
+ break;
877
+
878
+ if (( para = (q != text) )) {
879
+ Line anchor;
880
+
881
+ anchor.next = text;
882
+ ___mkd_freeLineRange(&anchor,q);
883
+ text = q;
884
+
784
885
  }
785
- else label = 0;
786
886
 
887
+ if ( kind == 2 && is_extra_dd(q) )
888
+ goto dd_block;
889
+ }
890
+ top->text = 0;
891
+ top->down = T(d);
892
+ return text;
893
+ }
894
+
895
+
896
+ static Line *
897
+ enumerated_block(Paragraph *top, int clip, MMIOT *f, int list_class)
898
+ {
899
+ ParagraphRoot d = { 0, 0 };
900
+ Paragraph *p;
901
+ Line *q = top->text, *text;
902
+ int para = 0, z;
903
+
904
+ while (( text = q )) {
905
+
787
906
  p = Pp(&d, text, LISTITEM);
788
- text = listitem(p, trim);
907
+ text = listitem(p, clip, f->flags, 0);
789
908
 
790
909
  p->down = compile(p->text, 0, f);
791
- p->text = label;
910
+ p->text = 0;
792
911
 
793
- if ( para && (top->typ != DL) && p->down ) p->down->align = PARA;
912
+ if ( para && p->down ) p->down->align = PARA;
794
913
 
795
- if ( !(q = skipempty(text)) || ((ltype = islist(q, &trim)) == 0)
796
- || (isdl != (ltype == DL)) )
914
+ if ( (q = skipempty(text)) == 0
915
+ || islist(q, &clip, f->flags, &z) != list_class )
797
916
  break;
798
917
 
799
918
  if ( para = (q != text) ) {
@@ -801,9 +920,9 @@ listblock(Paragraph *top, int trim, MMIOT *f)
801
920
 
802
921
  anchor.next = text;
803
922
  ___mkd_freeLineRange(&anchor, q);
804
- }
805
923
 
806
- if ( para && (top->typ != DL) && p->down ) p->down->align = PARA;
924
+ if ( p->down ) p->down->align = PARA;
925
+ }
807
926
  }
808
927
  top->text = 0;
809
928
  top->down = T(d);
@@ -838,7 +957,7 @@ addfootnote(Line *p, MMIOT* f)
838
957
  CREATE(foot->tag);
839
958
  CREATE(foot->link);
840
959
  CREATE(foot->title);
841
- foot->height = foot->width = 0;
960
+ foot->flags = foot->height = foot->width = 0;
842
961
 
843
962
  for (j=i=p->dle+1; T(p->text)[j] != ']'; j++)
844
963
  EXPAND(foot->tag) = T(p->text)[j];
@@ -847,6 +966,12 @@ addfootnote(Line *p, MMIOT* f)
847
966
  S(foot->tag)--;
848
967
  j = nextnonblank(p, j+2);
849
968
 
969
+ if ( (f->flags & MKD_EXTRA_FOOTNOTE) && (T(foot->tag)[0] == '^') ) {
970
+ while ( j < S(p->text) )
971
+ EXPAND(foot->title) = T(p->text)[j++];
972
+ goto skip_to_end;
973
+ }
974
+
850
975
  while ( (j < S(p->text)) && !isspace(T(p->text)[j]) )
851
976
  EXPAND(foot->link) = T(p->text)[j++];
852
977
  EXPAND(foot->link) = 0;
@@ -886,6 +1011,7 @@ addfootnote(Line *p, MMIOT* f)
886
1011
  --S(foot->title);
887
1012
  }
888
1013
 
1014
+ skip_to_end:
889
1015
  ___mkd_freeLine(p);
890
1016
  return np;
891
1017
  }
@@ -935,10 +1061,10 @@ compile_document(Line *ptr, MMIOT *f)
935
1061
  ANCHOR(Line) source = { 0, 0 };
936
1062
  Paragraph *p = 0;
937
1063
  struct kw *tag;
938
- int eaten;
1064
+ int eaten, unclosed;
939
1065
 
940
1066
  while ( ptr ) {
941
- if ( !(f->flags & DENY_HTML) && (tag = isopentag(ptr)) ) {
1067
+ if ( !(f->flags & MKD_NOHTML) && (tag = isopentag(ptr)) ) {
942
1068
  /* If we encounter a html/style block, compile and save all
943
1069
  * of the cached source BEFORE processing the html/style.
944
1070
  */
@@ -949,7 +1075,12 @@ compile_document(Line *ptr, MMIOT *f)
949
1075
  T(source) = E(source) = 0;
950
1076
  }
951
1077
  p = Pp(&d, ptr, strcmp(tag->id, "STYLE") == 0 ? STYLE : HTML);
952
- ptr = htmlblock(p, tag);
1078
+ ptr = htmlblock(p, tag, &unclosed);
1079
+ if ( unclosed ) {
1080
+ p->typ = SOURCE;
1081
+ p->down = compile(p->text, 1, f);
1082
+ p->text = 0;
1083
+ }
953
1084
  }
954
1085
  else if ( isfootnote(ptr) ) {
955
1086
  /* footnotes, like cats, sleep anywhere; pull them
@@ -991,7 +1122,7 @@ compile(Line *ptr, int toplevel, MMIOT *f)
991
1122
  Line *r;
992
1123
  int para = toplevel;
993
1124
  int blocks = 0;
994
- int hdr_type, list_type, indent;
1125
+ int hdr_type, list_type, list_class, indent;
995
1126
 
996
1127
  ptr = consume(ptr, &para);
997
1128
 
@@ -1014,13 +1145,19 @@ compile(Line *ptr, int toplevel, MMIOT *f)
1014
1145
  ptr = ptr->next;
1015
1146
  ___mkd_freeLine(r);
1016
1147
  }
1017
- else if (( list_type = islist(ptr, &indent) )) {
1018
- p = Pp(&d, ptr, list_type);
1019
- ptr = listblock(p, indent, f);
1148
+ else if (( list_class = islist(ptr, &indent, f->flags, &list_type) )) {
1149
+ if ( list_class == DL ) {
1150
+ p = Pp(&d, ptr, DL);
1151
+ ptr = definition_block(p, indent, f, list_type);
1152
+ }
1153
+ else {
1154
+ p = Pp(&d, ptr, list_type);
1155
+ ptr = enumerated_block(p, indent, f, list_class);
1156
+ }
1020
1157
  }
1021
1158
  else if ( isquote(ptr) ) {
1022
1159
  p = Pp(&d, ptr, QUOTE);
1023
- ptr = quoteblock(p);
1160
+ ptr = quoteblock(p, f->flags);
1024
1161
  p->down = compile(p->text, 1, f);
1025
1162
  p->text = 0;
1026
1163
  }
@@ -1028,13 +1165,13 @@ compile(Line *ptr, int toplevel, MMIOT *f)
1028
1165
  p = Pp(&d, ptr, HDR);
1029
1166
  ptr = headerblock(p, hdr_type);
1030
1167
  }
1031
- else if ( istable(ptr) && !(f->flags & (STRICT|NOTABLES)) ) {
1168
+ else if ( istable(ptr) && !(f->flags & (MKD_STRICT|MKD_NOTABLES)) ) {
1032
1169
  p = Pp(&d, ptr, TABLE);
1033
1170
  ptr = tableblock(p);
1034
1171
  }
1035
1172
  else {
1036
1173
  p = Pp(&d, ptr, MARKUP);
1037
- ptr = textblock(p, toplevel);
1174
+ ptr = textblock(p, toplevel, f->flags);
1038
1175
  }
1039
1176
 
1040
1177
  if ( (para||toplevel) && !p->align )
@@ -1052,19 +1189,6 @@ compile(Line *ptr, int toplevel, MMIOT *f)
1052
1189
  }
1053
1190
 
1054
1191
 
1055
- void
1056
- mkd_initialize()
1057
- {
1058
- static int first = 1;
1059
-
1060
- if ( first-- > 0 ) {
1061
- first = 0;
1062
- INITRNG(time(0));
1063
- mkd_prepare_tags();
1064
- }
1065
- }
1066
-
1067
-
1068
1192
  /*
1069
1193
  * the guts of the markdown() function, ripped out so I can do
1070
1194
  * debugging.
@@ -1074,7 +1198,7 @@ mkd_initialize()
1074
1198
  * prepare and compile `text`, returning a Paragraph tree.
1075
1199
  */
1076
1200
  int
1077
- mkd_compile(Document *doc, int flags)
1201
+ mkd_compile(Document *doc, DWORD flags)
1078
1202
  {
1079
1203
  if ( !doc )
1080
1204
  return 0;
@@ -1084,6 +1208,7 @@ mkd_compile(Document *doc, int flags)
1084
1208
 
1085
1209
  doc->compiled = 1;
1086
1210
  memset(doc->ctx, 0, sizeof(MMIOT) );
1211
+ doc->ctx->ref_prefix= doc->ref_prefix;
1087
1212
  doc->ctx->cb = &(doc->cb);
1088
1213
  doc->ctx->flags = flags & USER_FLAGS;
1089
1214
  CREATE(doc->ctx->in);