bluecloth 2.0.9 → 2.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data.tar.gz.sig +0 -0
  2. data/ChangeLog +29 -2
  3. data/Rakefile +18 -15
  4. data/ext/VERSION +1 -1
  5. data/ext/bluecloth.c +26 -5
  6. data/ext/config.h +13 -2
  7. data/ext/css.c +14 -5
  8. data/ext/cstring.h +1 -1
  9. data/ext/docheader.c +13 -7
  10. data/ext/emmatch.c +1 -1
  11. data/ext/generate.c +134 -48
  12. data/ext/markdown.c +207 -94
  13. data/ext/markdown.h +37 -28
  14. data/ext/mkdio.c +39 -32
  15. data/ext/mkdio.h +34 -24
  16. data/ext/resource.c +3 -1
  17. data/ext/setup.c +47 -0
  18. data/ext/tags.c +15 -2
  19. data/ext/tags.h +1 -0
  20. data/lib/bluecloth.rb +65 -40
  21. data/rake/documentation.rb +9 -1
  22. data/rake/hg.rb +34 -3
  23. data/rake/packaging.rb +1 -1
  24. data/rake/publishing.rb +2 -9
  25. data/rake/testing.rb +53 -88
  26. data/spec/bluecloth/101_changes_spec.rb +17 -17
  27. data/spec/bluecloth/autolinks_spec.rb +1 -1
  28. data/spec/bluecloth/blockquotes_spec.rb +18 -18
  29. data/spec/bluecloth/code_spans_spec.rb +1 -1
  30. data/spec/bluecloth/emphasis_spec.rb +1 -1
  31. data/spec/bluecloth/entities_spec.rb +1 -1
  32. data/spec/bluecloth/hrules_spec.rb +1 -1
  33. data/spec/bluecloth/images_spec.rb +1 -1
  34. data/spec/bluecloth/inline_html_spec.rb +1 -1
  35. data/spec/bluecloth/links_spec.rb +1 -1
  36. data/spec/bluecloth/lists_spec.rb +1 -1
  37. data/spec/bluecloth/paragraphs_spec.rb +1 -1
  38. data/spec/bluecloth/titles_spec.rb +1 -1
  39. data/spec/bluecloth_spec.rb +13 -13
  40. data/spec/bugfix_spec.rb +6 -1
  41. data/spec/contributions_spec.rb +1 -1
  42. data/spec/discount_spec.rb +2 -2
  43. data/spec/lib/helpers.rb +1 -124
  44. data/spec/lib/matchers.rb +1 -1
  45. data/spec/markdowntest_spec.rb +1 -1
  46. metadata +10 -10
  47. metadata.gz.sig +0 -0
@@ -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;
@@ -602,12 +670,16 @@ szmarkerclass(char *p)
602
670
  * marker %[kind:]name%
603
671
  */
604
672
  static int
605
- isdivmarker(Line *p, int start)
673
+ isdivmarker(Line *p, int start, DWORD flags)
606
674
  {
607
- #if DIV_QUOTE
608
- char *s = T(p->text);
609
- int len = S(p->text);
610
- int i;
675
+ char *s;
676
+ int len, i;
677
+
678
+ if ( flags & (MKD_NODIVQUOTE|MKD_STRICT) )
679
+ return 0;
680
+
681
+ len = S(p->text);
682
+ s = T(p->text);
611
683
 
612
684
  if ( !(len && s[start] == '%' && s[len-1] == '%') ) return 0;
613
685
 
@@ -619,9 +691,6 @@ isdivmarker(Line *p, int start)
619
691
  return 0;
620
692
 
621
693
  return 1;
622
- #else
623
- return 0;
624
- #endif
625
694
  }
626
695
 
627
696
 
@@ -637,7 +706,7 @@ isdivmarker(Line *p, int start)
637
706
  * way the markdown sample web form at Daring Fireball works.
638
707
  */
639
708
  static Line *
640
- quoteblock(Paragraph *p)
709
+ quoteblock(Paragraph *p, DWORD flags)
641
710
  {
642
711
  Line *t, *q;
643
712
  int qp;
@@ -660,13 +729,13 @@ quoteblock(Paragraph *p)
660
729
 
661
730
  q = skipempty(t->next);
662
731
 
663
- if ( (q == 0) || ((q != t->next) && (!isquote(q) || isdivmarker(q,1))) ) {
732
+ if ( (q == 0) || ((q != t->next) && (!isquote(q) || isdivmarker(q,1,flags))) ) {
664
733
  ___mkd_freeLineRange(t, q);
665
734
  t = q;
666
735
  break;
667
736
  }
668
737
  }
669
- if ( isdivmarker(p->text,0) ) {
738
+ if ( isdivmarker(p->text,0,flags) ) {
670
739
  char *prefix = "class";
671
740
  int i;
672
741
 
@@ -709,6 +778,8 @@ tableblock(Paragraph *p)
709
778
  static Paragraph *Pp(ParagraphRoot *, Line *, int);
710
779
  static Paragraph *compile(Line *, int, MMIOT *);
711
780
 
781
+ typedef int (*linefn)(Line *);
782
+
712
783
 
713
784
  /*
714
785
  * pull in a list block. A list block starts with a list marker and
@@ -717,7 +788,7 @@ static Paragraph *compile(Line *, int, MMIOT *);
717
788
  * marker, but multiple paragraphs need to start with a 4-space indent.
718
789
  */
719
790
  static Line *
720
- listitem(Paragraph *p, int indent)
791
+ listitem(Paragraph *p, int indent, DWORD flags, linefn check)
721
792
  {
722
793
  Line *t, *q;
723
794
  int clip = indent;
@@ -748,7 +819,9 @@ listitem(Paragraph *p, int indent)
748
819
  indent = clip ? clip : 2;
749
820
  }
750
821
 
751
- if ( (q->dle < indent) && (ishr(q) || islist(q,&z)) && !issetext(q,&z) ) {
822
+ if ( (q->dle < indent) && (ishr(q) || islist(q,&z,flags,&z)
823
+ || (check && (*check)(q)))
824
+ && !issetext(q,&z) ) {
752
825
  q = t->next;
753
826
  t->next = 0;
754
827
  return q;
@@ -761,39 +834,81 @@ listitem(Paragraph *p, int indent)
761
834
 
762
835
 
763
836
  static Line *
764
- listblock(Paragraph *top, int trim, MMIOT *f)
837
+ definition_block(Paragraph *top, int clip, MMIOT *f, int kind)
765
838
  {
766
839
  ParagraphRoot d = { 0, 0 };
767
840
  Paragraph *p;
768
- Line *q = top->text, *text, *label;
769
- int isdl = (top->typ == DL),
770
- para = 0,
771
- ltype;
841
+ Line *q = top->text, *text = 0, *labels;
842
+ int z, para;
772
843
 
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;
844
+ while (( labels = q )) {
845
+
846
+ if ( (q = isdefinition(labels, &z, &kind)) == 0 )
847
+ break;
848
+
849
+ if ( (text = skipempty(q->next)) == 0 )
850
+ break;
851
+
852
+ if (( para = (text != q->next) ))
853
+ ___mkd_freeLineRange(q, text);
854
+
855
+ q->next = 0;
856
+ if ( kind == 1 /* discount dl */ )
857
+ for ( q = labels; q; q = q->next ) {
858
+ CLIP(q->text, 0, 1);
859
+ S(q->text)--;
783
860
  }
861
+
862
+ dd_block:
863
+ p = Pp(&d, text, LISTITEM);
864
+
865
+ text = listitem(p, clip, f->flags, (kind==2) ? is_extra_dd : 0);
866
+ p->down = compile(p->text, 0, f);
867
+ p->text = labels; labels = 0;
868
+
869
+ if ( para && p->down ) p->down->align = PARA;
870
+
871
+ if ( (q = skipempty(text)) == 0 )
872
+ break;
873
+
874
+ if (( para = (q != text) )) {
875
+ Line anchor;
876
+
877
+ anchor.next = text;
878
+ ___mkd_freeLineRange(&anchor,q);
879
+ text = q;
880
+
784
881
  }
785
- else label = 0;
786
882
 
883
+ if ( kind == 2 && is_extra_dd(q) )
884
+ goto dd_block;
885
+ }
886
+ top->text = 0;
887
+ top->down = T(d);
888
+ return text;
889
+ }
890
+
891
+
892
+ static Line *
893
+ enumerated_block(Paragraph *top, int clip, MMIOT *f, int list_class)
894
+ {
895
+ ParagraphRoot d = { 0, 0 };
896
+ Paragraph *p;
897
+ Line *q = top->text, *text;
898
+ int para = 0, z;
899
+
900
+ while (( text = q )) {
901
+
787
902
  p = Pp(&d, text, LISTITEM);
788
- text = listitem(p, trim);
903
+ text = listitem(p, clip, f->flags, 0);
789
904
 
790
905
  p->down = compile(p->text, 0, f);
791
- p->text = label;
906
+ p->text = 0;
792
907
 
793
- if ( para && (top->typ != DL) && p->down ) p->down->align = PARA;
908
+ if ( para && p->down ) p->down->align = PARA;
794
909
 
795
- if ( !(q = skipempty(text)) || ((ltype = islist(q, &trim)) == 0)
796
- || (isdl != (ltype == DL)) )
910
+ if ( (q = skipempty(text)) == 0
911
+ || islist(q, &clip, f->flags, &z) != list_class )
797
912
  break;
798
913
 
799
914
  if ( para = (q != text) ) {
@@ -801,9 +916,9 @@ listblock(Paragraph *top, int trim, MMIOT *f)
801
916
 
802
917
  anchor.next = text;
803
918
  ___mkd_freeLineRange(&anchor, q);
804
- }
805
919
 
806
- if ( para && (top->typ != DL) && p->down ) p->down->align = PARA;
920
+ if ( p->down ) p->down->align = PARA;
921
+ }
807
922
  }
808
923
  top->text = 0;
809
924
  top->down = T(d);
@@ -935,10 +1050,10 @@ compile_document(Line *ptr, MMIOT *f)
935
1050
  ANCHOR(Line) source = { 0, 0 };
936
1051
  Paragraph *p = 0;
937
1052
  struct kw *tag;
938
- int eaten;
1053
+ int eaten, unclosed;
939
1054
 
940
1055
  while ( ptr ) {
941
- if ( !(f->flags & DENY_HTML) && (tag = isopentag(ptr)) ) {
1056
+ if ( !(f->flags & MKD_NOHTML) && (tag = isopentag(ptr)) ) {
942
1057
  /* If we encounter a html/style block, compile and save all
943
1058
  * of the cached source BEFORE processing the html/style.
944
1059
  */
@@ -949,7 +1064,12 @@ compile_document(Line *ptr, MMIOT *f)
949
1064
  T(source) = E(source) = 0;
950
1065
  }
951
1066
  p = Pp(&d, ptr, strcmp(tag->id, "STYLE") == 0 ? STYLE : HTML);
952
- ptr = htmlblock(p, tag);
1067
+ ptr = htmlblock(p, tag, &unclosed);
1068
+ if ( unclosed ) {
1069
+ p->typ = SOURCE;
1070
+ p->down = compile(p->text, 1, f);
1071
+ p->text = 0;
1072
+ }
953
1073
  }
954
1074
  else if ( isfootnote(ptr) ) {
955
1075
  /* footnotes, like cats, sleep anywhere; pull them
@@ -991,7 +1111,7 @@ compile(Line *ptr, int toplevel, MMIOT *f)
991
1111
  Line *r;
992
1112
  int para = toplevel;
993
1113
  int blocks = 0;
994
- int hdr_type, list_type, indent;
1114
+ int hdr_type, list_type, list_class, indent;
995
1115
 
996
1116
  ptr = consume(ptr, &para);
997
1117
 
@@ -1014,13 +1134,19 @@ compile(Line *ptr, int toplevel, MMIOT *f)
1014
1134
  ptr = ptr->next;
1015
1135
  ___mkd_freeLine(r);
1016
1136
  }
1017
- else if (( list_type = islist(ptr, &indent) )) {
1018
- p = Pp(&d, ptr, list_type);
1019
- ptr = listblock(p, indent, f);
1137
+ else if (( list_class = islist(ptr, &indent, f->flags, &list_type) )) {
1138
+ if ( list_class == DL ) {
1139
+ p = Pp(&d, ptr, DL);
1140
+ ptr = definition_block(p, indent, f, list_type);
1141
+ }
1142
+ else {
1143
+ p = Pp(&d, ptr, list_type);
1144
+ ptr = enumerated_block(p, indent, f, list_class);
1145
+ }
1020
1146
  }
1021
1147
  else if ( isquote(ptr) ) {
1022
1148
  p = Pp(&d, ptr, QUOTE);
1023
- ptr = quoteblock(p);
1149
+ ptr = quoteblock(p, f->flags);
1024
1150
  p->down = compile(p->text, 1, f);
1025
1151
  p->text = 0;
1026
1152
  }
@@ -1028,13 +1154,13 @@ compile(Line *ptr, int toplevel, MMIOT *f)
1028
1154
  p = Pp(&d, ptr, HDR);
1029
1155
  ptr = headerblock(p, hdr_type);
1030
1156
  }
1031
- else if ( istable(ptr) && !(f->flags & (STRICT|NOTABLES)) ) {
1157
+ else if ( istable(ptr) && !(f->flags & (MKD_STRICT|MKD_NOTABLES)) ) {
1032
1158
  p = Pp(&d, ptr, TABLE);
1033
1159
  ptr = tableblock(p);
1034
1160
  }
1035
1161
  else {
1036
1162
  p = Pp(&d, ptr, MARKUP);
1037
- ptr = textblock(p, toplevel);
1163
+ ptr = textblock(p, toplevel, f->flags);
1038
1164
  }
1039
1165
 
1040
1166
  if ( (para||toplevel) && !p->align )
@@ -1052,19 +1178,6 @@ compile(Line *ptr, int toplevel, MMIOT *f)
1052
1178
  }
1053
1179
 
1054
1180
 
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
1181
  /*
1069
1182
  * the guts of the markdown() function, ripped out so I can do
1070
1183
  * debugging.
@@ -1074,7 +1187,7 @@ mkd_initialize()
1074
1187
  * prepare and compile `text`, returning a Paragraph tree.
1075
1188
  */
1076
1189
  int
1077
- mkd_compile(Document *doc, int flags)
1190
+ mkd_compile(Document *doc, DWORD flags)
1078
1191
  {
1079
1192
  if ( !doc )
1080
1193
  return 0;