rdiscount 1.6.8 → 2.0.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.
@@ -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);