bluecloth 2.0.7-x86-mingw32 → 2.0.11pre158-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.gemtest +0 -0
  3. data/History.md +4 -0
  4. data/LICENSE +1 -1
  5. data/Manifest.txt +103 -0
  6. data/README.md +103 -0
  7. data/Rakefile +95 -301
  8. data/ext/VERSION +1 -1
  9. data/ext/bluecloth.c +69 -23
  10. data/ext/bluecloth.h +13 -2
  11. data/ext/config.h +13 -2
  12. data/ext/css.c +14 -5
  13. data/ext/cstring.h +4 -2
  14. data/ext/docheader.c +13 -7
  15. data/ext/emmatch.c +188 -0
  16. data/ext/extconf.rb +7 -9
  17. data/ext/generate.c +333 -293
  18. data/ext/html5.c +24 -0
  19. data/ext/markdown.c +326 -185
  20. data/ext/markdown.h +52 -29
  21. data/ext/mkdio.c +82 -41
  22. data/ext/mkdio.h +44 -23
  23. data/ext/resource.c +4 -2
  24. data/ext/setup.c +47 -0
  25. data/ext/tags.c +123 -0
  26. data/ext/tags.h +19 -0
  27. data/lib/1.8/bluecloth_ext.so +0 -0
  28. data/lib/1.9/bluecloth_ext.so +0 -0
  29. data/lib/bluecloth.rb +77 -42
  30. data/spec/bluecloth/101_changes_spec.rb +18 -21
  31. data/spec/bluecloth/TEMPLATE +36 -0
  32. data/spec/bluecloth/autolinks_spec.rb +4 -7
  33. data/spec/bluecloth/blockquotes_spec.rb +20 -23
  34. data/spec/bluecloth/code_spans_spec.rb +2 -5
  35. data/spec/bluecloth/emphasis_spec.rb +2 -5
  36. data/spec/bluecloth/entities_spec.rb +2 -5
  37. data/spec/bluecloth/hrules_spec.rb +2 -5
  38. data/spec/bluecloth/images_spec.rb +2 -5
  39. data/spec/bluecloth/inline_html_spec.rb +26 -66
  40. data/spec/bluecloth/links_spec.rb +1 -5
  41. data/spec/bluecloth/lists_spec.rb +2 -5
  42. data/spec/bluecloth/paragraphs_spec.rb +2 -5
  43. data/spec/bluecloth/titles_spec.rb +2 -5
  44. data/spec/bluecloth_spec.rb +36 -22
  45. data/spec/bugfix_spec.rb +90 -10
  46. data/spec/contributions_spec.rb +2 -3
  47. data/spec/discount_spec.rb +50 -10
  48. data/spec/lib/helpers.rb +18 -117
  49. data/spec/lib/matchers.rb +7 -18
  50. data/spec/markdowntest_spec.rb +3 -39
  51. metadata +257 -143
  52. metadata.gz.sig +0 -0
  53. data/ChangeLog +0 -387
  54. data/README +0 -81
  55. data/Rakefile.local +0 -41
  56. data/rake/191_compat.rb +0 -26
  57. data/rake/dependencies.rb +0 -76
  58. data/rake/helpers.rb +0 -435
  59. data/rake/hg.rb +0 -273
  60. data/rake/manual.rb +0 -782
  61. data/rake/packaging.rb +0 -123
  62. data/rake/publishing.rb +0 -274
  63. data/rake/rdoc.rb +0 -30
  64. data/rake/style.rb +0 -62
  65. data/rake/svn.rb +0 -668
  66. data/rake/testing.rb +0 -187
  67. data/rake/verifytask.rb +0 -64
data/ext/html5.c ADDED
@@ -0,0 +1,24 @@
1
+ /* block-level tags for passing html5 blocks through the blender
2
+ */
3
+ #include "tags.h"
4
+
5
+ void
6
+ mkd_with_html5_tags()
7
+ {
8
+ static int populated = 0;
9
+
10
+ if ( populated ) return;
11
+ populated = 1;
12
+
13
+ mkd_prepare_tags();
14
+
15
+ mkd_define_tag("ASIDE", 0);
16
+ mkd_define_tag("FOOTER", 0);
17
+ mkd_define_tag("HEADER", 0);
18
+ mkd_define_tag("HGROUP", 0);
19
+ mkd_define_tag("NAV", 0);
20
+ mkd_define_tag("SECTION", 0);
21
+ mkd_define_tag("ARTICLE", 0);
22
+
23
+ mkd_sort_tags();
24
+ }
data/ext/markdown.c CHANGED
@@ -4,6 +4,8 @@
4
4
  * The redistribution terms are provided in the COPYRIGHT file that must
5
5
  * be distributed with this source code.
6
6
  */
7
+ #include "config.h"
8
+
7
9
  #include <stdio.h>
8
10
  #include <string.h>
9
11
  #include <stdarg.h>
@@ -11,51 +13,15 @@
11
13
  #include <time.h>
12
14
  #include <ctype.h>
13
15
 
14
- #include "config.h"
15
-
16
16
  #include "cstring.h"
17
17
  #include "markdown.h"
18
18
  #include "amalloc.h"
19
-
20
- /* block-level tags for passing html blocks through the blender
21
- */
22
- struct kw {
23
- char *id;
24
- int size;
25
- int selfclose;
26
- } ;
27
-
28
- #define KW(x) { x, sizeof(x)-1, 0 }
29
- #define SC(x) { x, sizeof(x)-1, 1 }
30
-
31
- static struct kw blocktags[] = { KW("!--"), KW("STYLE"), KW("SCRIPT"),
32
- KW("ADDRESS"), KW("BDO"), KW("BLOCKQUOTE"),
33
- KW("CENTER"), KW("DFN"), KW("DIV"), KW("H1"),
34
- KW("H2"), KW("H3"), KW("H4"), KW("H5"),
35
- KW("H6"), KW("LISTING"), KW("NOBR"),
36
- KW("UL"), KW("P"), KW("OL"), KW("DL"),
37
- KW("PLAINTEXT"), KW("PRE"), KW("TABLE"),
38
- KW("WBR"), KW("XMP"), SC("HR"), SC("BR"),
39
- KW("IFRAME"), KW("MAP") };
40
- #define SZTAGS (sizeof blocktags / sizeof blocktags[0])
41
- #define MAXTAG 11 /* sizeof "BLOCKQUOTE" */
19
+ #include "tags.h"
42
20
 
43
21
  typedef int (*stfu)(const void*,const void*);
44
22
 
45
23
  typedef ANCHOR(Paragraph) ParagraphRoot;
46
24
 
47
-
48
- /* case insensitive string sort (for qsort() and bsearch() of block tags)
49
- */
50
- static int
51
- casort(struct kw *a, struct kw *b)
52
- {
53
- if ( a->size != b->size )
54
- return a->size - b->size;
55
- return strncasecmp(a->id, b->id, b->size);
56
- }
57
-
58
-
59
25
  /* case insensitive string sort for Footnote tags.
60
26
  */
61
27
  int
@@ -135,19 +101,28 @@ ___mkd_tidy(Cstring *t)
135
101
  }
136
102
 
137
103
 
104
+ static struct kw comment = { "!--", 3, 0 };
105
+
138
106
  static struct kw *
139
107
  isopentag(Line *p)
140
108
  {
141
109
  int i=0, len;
142
- struct kw key, *ret;
110
+ char *line;
143
111
 
144
112
  if ( !p ) return 0;
145
113
 
114
+ line = T(p->text);
146
115
  len = S(p->text);
147
116
 
148
- if ( len < 3 || T(p->text)[0] != '<' )
117
+ if ( len < 3 || line[0] != '<' )
149
118
  return 0;
150
119
 
120
+ if ( line[1] == '!' && line[2] == '-' && line[3] == '-' )
121
+ /* comments need special case handling, because
122
+ * the !-- doesn't need to end in a whitespace
123
+ */
124
+ return &comment;
125
+
151
126
  /* find how long the tag is so we can check to see if
152
127
  * it's a block-level tag
153
128
  */
@@ -156,13 +131,8 @@ isopentag(Line *p)
156
131
  && !isspace(T(p->text)[i]); ++i )
157
132
  ;
158
133
 
159
- key.id = T(p->text)+1;
160
- key.size = i-1;
161
-
162
- if ( ret = bsearch(&key, blocktags, SZTAGS, sizeof key, (stfu)casort))
163
- return ret;
164
134
 
165
- return 0;
135
+ return mkd_search_tags(T(p->text)+1, i-1);
166
136
  }
167
137
 
168
138
 
@@ -171,6 +141,8 @@ typedef struct _flo {
171
141
  int i;
172
142
  } FLO;
173
143
 
144
+ #define floindex(x) (x.i)
145
+
174
146
 
175
147
  static int
176
148
  flogetc(FLO *f)
@@ -186,15 +158,56 @@ flogetc(FLO *f)
186
158
  }
187
159
 
188
160
 
161
+ static void
162
+ splitline(Line *t, int cutpoint)
163
+ {
164
+ if ( t && (cutpoint < S(t->text)) ) {
165
+ Line *tmp = calloc(1, sizeof *tmp);
166
+
167
+ tmp->next = t->next;
168
+ t->next = tmp;
169
+
170
+ tmp->dle = t->dle;
171
+ SUFFIX(tmp->text, T(t->text)+cutpoint, S(t->text)-cutpoint);
172
+ S(t->text) = cutpoint;
173
+ }
174
+ }
175
+
176
+
177
+ static Line *
178
+ commentblock(Paragraph *p, int *unclosed)
179
+ {
180
+ Line *t, *ret;
181
+ char *end;
182
+
183
+ for ( t = p->text; t ; t = t->next) {
184
+ if ( end = strstr(T(t->text), "-->") ) {
185
+ splitline(t, 3 + (end - T(t->text)) );
186
+ ret = t->next;
187
+ t->next = 0;
188
+ return ret;
189
+ }
190
+ }
191
+ *unclosed = 1;
192
+ return t;
193
+
194
+ }
195
+
196
+
189
197
  static Line *
190
- htmlblock(Paragraph *p, struct kw *tag)
198
+ htmlblock(Paragraph *p, struct kw *tag, int *unclosed)
191
199
  {
192
200
  Line *ret;
193
201
  FLO f = { p->text, 0 };
194
202
  int c;
195
203
  int i, closing, depth=0;
196
204
 
197
- if ( tag->selfclose || (tag->size >= MAXTAG) ) {
205
+ *unclosed = 0;
206
+
207
+ if ( tag == &comment )
208
+ return commentblock(p, unclosed);
209
+
210
+ if ( tag->selfclose ) {
198
211
  ret = f.t->next;
199
212
  f.t->next = 0;
200
213
  return ret;
@@ -230,8 +243,11 @@ htmlblock(Paragraph *p, struct kw *tag)
230
243
  /* consume trailing gunk in close tag */
231
244
  c = flogetc(&f);
232
245
  }
246
+ if ( c == EOF )
247
+ break;
233
248
  if ( !f.t )
234
249
  return 0;
250
+ splitline(f.t, floindex(f));
235
251
  ret = f.t->next;
236
252
  f.t->next = 0;
237
253
  return ret;
@@ -240,27 +256,11 @@ htmlblock(Paragraph *p, struct kw *tag)
240
256
  }
241
257
  }
242
258
  }
259
+ *unclosed = 1;
243
260
  return 0;
244
261
  }
245
262
 
246
263
 
247
- static Line *
248
- comment(Paragraph *p)
249
- {
250
- Line *t, *ret;
251
-
252
- for ( t = p->text; t ; t = t->next) {
253
- if ( strstr(T(t->text), "-->") ) {
254
- ret = t->next;
255
- t->next = 0;
256
- return ret;
257
- }
258
- }
259
- return t;
260
-
261
- }
262
-
263
-
264
264
  /* tables look like
265
265
  * header|header{|header}
266
266
  * ------|------{|......}
@@ -305,8 +305,8 @@ isfootnote(Line *t)
305
305
  for ( ++i; i < S(t->text) ; ++i ) {
306
306
  if ( T(t->text)[i] == '[' )
307
307
  return 0;
308
- else if ( T(t->text)[i] == ']' && T(t->text)[i+1] == ':' )
309
- return 1;
308
+ else if ( T(t->text)[i] == ']' )
309
+ return ( T(t->text)[i+1] == ':' ) ;
310
310
  }
311
311
  return 0;
312
312
  }
@@ -315,7 +315,14 @@ isfootnote(Line *t)
315
315
  static int
316
316
  isquote(Line *t)
317
317
  {
318
- return ( T(t->text)[0] == '>' );
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;
319
326
  }
320
327
 
321
328
 
@@ -355,6 +362,34 @@ ishr(Line *t)
355
362
  }
356
363
 
357
364
 
365
+ static int
366
+ issetext(Line *t, int *htyp)
367
+ {
368
+ int i;
369
+ /* then check for setext-style HEADER
370
+ * ======
371
+ */
372
+
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;
381
+
382
+ for (i=1; i < last; i++)
383
+ if ( q[0] != q[i] )
384
+ return 0;
385
+ *htyp = SETEXT;
386
+ return 1;
387
+ }
388
+ }
389
+ return 0;
390
+ }
391
+
392
+
358
393
  static int
359
394
  ishdr(Line *t, int *htyp)
360
395
  {
@@ -376,75 +411,116 @@ ishdr(Line *t, int *htyp)
376
411
  return 1;
377
412
  }
378
413
 
379
- /* then check for setext-style HEADER
380
- * ======
381
- */
414
+ return issetext(t, htyp);
415
+ }
382
416
 
383
- if ( t->next ) {
384
- char *q = T(t->next->text);
385
417
 
386
- if ( (*q == '=') || (*q == '-') ) {
387
- for (i=1; i < S(t->next->text); i++)
388
- if ( q[0] != q[i] )
389
- return 0;
390
- *htyp = SETEXT;
391
- return 1;
418
+ static Line*
419
+ is_discount_dt(Line *t, int *clip)
420
+ {
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;
392
430
  }
431
+ else
432
+ return is_discount_dt(t->next, clip);
393
433
  }
434
+ #endif
394
435
  return 0;
395
436
  }
396
437
 
397
438
 
398
439
  static int
399
- isdefinition(Line *t)
440
+ is_extra_dd(Line *t)
400
441
  {
401
- #if DL_TAG_EXTENSION
402
- return t && t->next
403
- && (S(t->text) > 2)
404
- && (t->dle == 0)
405
- && (T(t->text)[0] == '=')
406
- && (T(t->text)[S(t->text)-1] == '=')
407
- && ( (t->next->dle >= 4) || isdefinition(t->next) );
408
- #else
409
- return 0;
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
+ }
410
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);
411
484
  }
412
485
 
413
486
 
414
487
  static int
415
- islist(Line *t, int *trim)
488
+ islist(Line *t, int *clip, DWORD flags, int *list_type)
416
489
  {
417
490
  int i, j;
418
491
  char *q;
419
492
 
420
- if ( iscode(t) || blankline(t) || ishdr(t,&i) || ishr(t) )
493
+ if ( /*iscode(t) ||*/ blankline(t) || ishdr(t,&i) || ishr(t) )
421
494
  return 0;
422
495
 
423
- if ( isdefinition(t) ) {
424
- *trim = 4;
496
+ if ( !(flags & (MKD_NODLIST|MKD_STRICT)) && isdefinition(t,clip,list_type) )
425
497
  return DL;
426
- }
427
498
 
428
499
  if ( strchr("*-+", T(t->text)[t->dle]) && isspace(T(t->text)[t->dle+1]) ) {
429
500
  i = nextnonblank(t, t->dle+1);
430
- *trim = (i > 4) ? 4 : i;
431
- return UL;
501
+ *clip = (i > 4) ? 4 : i;
502
+ *list_type = UL;
503
+ return AL;
432
504
  }
433
505
 
434
506
  if ( (j = nextblank(t,t->dle)) > t->dle ) {
435
507
  if ( T(t->text)[j-1] == '.' ) {
436
- #if ALPHA_LIST
437
- if ( (j == t->dle + 2) && isalpha(T(t->text)[t->dle]) ) {
438
- j = nextnonblank(t,j);
439
- *trim = j;
440
- return AL;
441
- }
442
- #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
+
443
518
  strtoul(T(t->text)+t->dle, &q, 10);
444
519
  if ( (q > T(t->text)+t->dle) && (q == T(t->text) + (j-1)) ) {
445
520
  j = nextnonblank(t,j);
446
- *trim = j;
447
- return OL;
521
+ *clip = (j > 4) ? 4 : j;
522
+ *list_type = OL;
523
+ return AL;
448
524
  }
449
525
  }
450
526
  }
@@ -475,7 +551,8 @@ headerblock(Paragraph *pp, int htyp)
475
551
  * the leading and trailing `#`'s
476
552
  */
477
553
 
478
- for (i=0; (T(p->text)[i] == T(p->text)[0]) && (i < S(p->text)-1); i++)
554
+ for (i=0; (T(p->text)[i] == T(p->text)[0]) && (i < S(p->text)-1)
555
+ && (i < 6); i++)
479
556
  ;
480
557
 
481
558
  pp->hnumber = i;
@@ -539,27 +616,33 @@ centered(Line *first, Line *last)
539
616
 
540
617
 
541
618
  static int
542
- endoftextblock(Line *t, int toplevelblock)
619
+ endoftextblock(Line *t, int toplevelblock, DWORD flags)
543
620
  {
544
621
  int z;
545
622
 
546
- 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) )
547
630
  return 1;
548
631
 
549
632
  /* HORRIBLE STANDARDS KLUDGE: Toplevel paragraphs eat absorb adjacent
550
633
  * list items, but sublevel blocks behave properly.
551
634
  */
552
- return toplevelblock ? 0 : islist(t,&z);
635
+ return toplevelblock ? 0 : islist(t,&z,flags, &z);
553
636
  }
554
637
 
555
638
 
556
639
  static Line *
557
- textblock(Paragraph *p, int toplevel)
640
+ textblock(Paragraph *p, int toplevel, DWORD flags)
558
641
  {
559
642
  Line *t, *next;
560
643
 
561
644
  for ( t = p->text; t ; t = next ) {
562
- if ( ((next = t->next) == 0) || endoftextblock(next, toplevel) ) {
645
+ if ( ((next = t->next) == 0) || endoftextblock(next, toplevel, flags) ) {
563
646
  p->align = centered(p->text, t);
564
647
  t->next = 0;
565
648
  return next;
@@ -586,27 +669,32 @@ szmarkerclass(char *p)
586
669
  * check if the first line of a quoted block is the special div-not-quote
587
670
  * marker %[kind:]name%
588
671
  */
672
+ #define iscsschar(c) (isalpha(c) || (c == '-') || (c == '_') )
673
+
589
674
  static int
590
- isdivmarker(Line *p, int start)
675
+ isdivmarker(Line *p, int start, DWORD flags)
591
676
  {
592
- #if DIV_QUOTE
593
- char *s = T(p->text);
594
- int len = S(p->text);
595
- int i;
677
+ char *s;
678
+ int last, i;
596
679
 
597
- 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;
598
688
 
599
- i = szmarkerclass(s+start+1)+start;
600
- len -= start+1;
689
+ i = szmarkerclass(s+1);
601
690
 
602
- while ( ++i < len )
603
- 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])) )
604
695
  return 0;
605
696
 
606
697
  return 1;
607
- #else
608
- return 0;
609
- #endif
610
698
  }
611
699
 
612
700
 
@@ -622,27 +710,36 @@ isdivmarker(Line *p, int start)
622
710
  * way the markdown sample web form at Daring Fireball works.
623
711
  */
624
712
  static Line *
625
- quoteblock(Paragraph *p)
713
+ quoteblock(Paragraph *p, DWORD flags)
626
714
  {
627
715
  Line *t, *q;
628
716
  int qp;
629
717
 
630
718
  for ( t = p->text; t ; t = q ) {
631
719
  if ( isquote(t) ) {
632
- qp = (T(t->text)[1] == ' ') ? 2 : 1;
720
+ /* clip leading spaces */
721
+ for (qp = 0; T(t->text)[qp] != '>'; qp ++)
722
+ /* assert: the first nonblank character on this line
723
+ * will be a >
724
+ */;
725
+ /* clip '>' */
726
+ qp++;
727
+ /* clip next space, if any */
728
+ if ( T(t->text)[qp] == ' ' )
729
+ qp++;
633
730
  CLIP(t->text, 0, qp);
634
731
  t->dle = mkd_firstnonblank(t);
635
732
  }
636
733
 
637
734
  q = skipempty(t->next);
638
735
 
639
- if ( (q == 0) || ((q != t->next) && (!isquote(q) || isdivmarker(q,1))) ) {
736
+ if ( (q == 0) || ((q != t->next) && (!isquote(q) || isdivmarker(q,1,flags))) ) {
640
737
  ___mkd_freeLineRange(t, q);
641
738
  t = q;
642
739
  break;
643
740
  }
644
741
  }
645
- if ( isdivmarker(p->text,0) ) {
742
+ if ( isdivmarker(p->text,0,flags) ) {
646
743
  char *prefix = "class";
647
744
  int i;
648
745
 
@@ -685,6 +782,8 @@ tableblock(Paragraph *p)
685
782
  static Paragraph *Pp(ParagraphRoot *, Line *, int);
686
783
  static Paragraph *compile(Line *, int, MMIOT *);
687
784
 
785
+ typedef int (*linefn)(Line *);
786
+
688
787
 
689
788
  /*
690
789
  * pull in a list block. A list block starts with a list marker and
@@ -693,7 +792,7 @@ static Paragraph *compile(Line *, int, MMIOT *);
693
792
  * marker, but multiple paragraphs need to start with a 4-space indent.
694
793
  */
695
794
  static Line *
696
- listitem(Paragraph *p, int indent)
795
+ listitem(Paragraph *p, int indent, DWORD flags, linefn check)
697
796
  {
698
797
  Line *t, *q;
699
798
  int clip = indent;
@@ -709,8 +808,9 @@ listitem(Paragraph *p, int indent)
709
808
  }
710
809
 
711
810
  /* after a blank line, the next block needs to start with a line
712
- * that's indented 4 spaces, but after that the line doesn't
713
- * need any indentation
811
+ * that's indented 4(? -- reference implementation allows a 1
812
+ * character indent, but that has unfortunate side effects here)
813
+ * spaces, but after that the line doesn't need any indentation
714
814
  */
715
815
  if ( q != t->next ) {
716
816
  if (q->dle < indent) {
@@ -718,10 +818,14 @@ listitem(Paragraph *p, int indent)
718
818
  t->next = 0;
719
819
  return q;
720
820
  }
721
- indent = 4;
821
+ /* indent at least 2, and at most as
822
+ * as far as the initial line was indented. */
823
+ indent = clip ? clip : 2;
722
824
  }
723
825
 
724
- if ( (q->dle < indent) && (ishr(q) || islist(q,&z)) && !ishdr(q,&z) ) {
826
+ if ( (q->dle < indent) && (ishr(q) || islist(q,&z,flags,&z)
827
+ || (check && (*check)(q)))
828
+ && !issetext(q,&z) ) {
725
829
  q = t->next;
726
830
  t->next = 0;
727
831
  return q;
@@ -734,39 +838,81 @@ listitem(Paragraph *p, int indent)
734
838
 
735
839
 
736
840
  static Line *
737
- listblock(Paragraph *top, int trim, MMIOT *f)
841
+ definition_block(Paragraph *top, int clip, MMIOT *f, int kind)
738
842
  {
739
843
  ParagraphRoot d = { 0, 0 };
740
844
  Paragraph *p;
741
- Line *q = top->text, *text, *label;
742
- int isdl = (top->typ == DL),
743
- para = 0,
744
- ltype;
845
+ Line *q = top->text, *text = 0, *labels;
846
+ int z, para;
745
847
 
746
- while (( text = q )) {
747
- if ( top->typ == DL ) {
748
- Line *lp;
749
-
750
- for ( lp = label = text; lp ; lp = lp->next ) {
751
- text = lp->next;
752
- CLIP(lp->text, 0, 1);
753
- S(lp->text)--;
754
- if ( !isdefinition(lp->next) )
755
- 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)--;
756
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
+
757
885
  }
758
- else label = 0;
759
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
+
760
906
  p = Pp(&d, text, LISTITEM);
761
- text = listitem(p, trim);
907
+ text = listitem(p, clip, f->flags, 0);
762
908
 
763
909
  p->down = compile(p->text, 0, f);
764
- p->text = label;
910
+ p->text = 0;
765
911
 
766
- if ( para && (top->typ != DL) && p->down ) p->down->align = PARA;
912
+ if ( para && p->down ) p->down->align = PARA;
767
913
 
768
- if ( !(q = skipempty(text)) || ((ltype = islist(q, &trim)) == 0)
769
- || (isdl != (ltype == DL)) )
914
+ if ( (q = skipempty(text)) == 0
915
+ || islist(q, &clip, f->flags, &z) != list_class )
770
916
  break;
771
917
 
772
918
  if ( para = (q != text) ) {
@@ -774,9 +920,9 @@ listblock(Paragraph *top, int trim, MMIOT *f)
774
920
 
775
921
  anchor.next = text;
776
922
  ___mkd_freeLineRange(&anchor, q);
777
- }
778
923
 
779
- if ( para && (top->typ != DL) && p->down ) p->down->align = PARA;
924
+ if ( p->down ) p->down->align = PARA;
925
+ }
780
926
  }
781
927
  top->text = 0;
782
928
  top->down = T(d);
@@ -908,10 +1054,10 @@ compile_document(Line *ptr, MMIOT *f)
908
1054
  ANCHOR(Line) source = { 0, 0 };
909
1055
  Paragraph *p = 0;
910
1056
  struct kw *tag;
911
- int eaten;
1057
+ int eaten, unclosed;
912
1058
 
913
1059
  while ( ptr ) {
914
- if ( !(f->flags & DENY_HTML) && (tag = isopentag(ptr)) ) {
1060
+ if ( !(f->flags & MKD_NOHTML) && (tag = isopentag(ptr)) ) {
915
1061
  /* If we encounter a html/style block, compile and save all
916
1062
  * of the cached source BEFORE processing the html/style.
917
1063
  */
@@ -922,10 +1068,12 @@ compile_document(Line *ptr, MMIOT *f)
922
1068
  T(source) = E(source) = 0;
923
1069
  }
924
1070
  p = Pp(&d, ptr, strcmp(tag->id, "STYLE") == 0 ? STYLE : HTML);
925
- if ( strcmp(tag->id, "!--") == 0 )
926
- ptr = comment(p);
927
- else
928
- ptr = htmlblock(p, tag);
1071
+ ptr = htmlblock(p, tag, &unclosed);
1072
+ if ( unclosed ) {
1073
+ p->typ = SOURCE;
1074
+ p->down = compile(p->text, 1, f);
1075
+ p->text = 0;
1076
+ }
929
1077
  }
930
1078
  else if ( isfootnote(ptr) ) {
931
1079
  /* footnotes, like cats, sleep anywhere; pull them
@@ -967,7 +1115,7 @@ compile(Line *ptr, int toplevel, MMIOT *f)
967
1115
  Line *r;
968
1116
  int para = toplevel;
969
1117
  int blocks = 0;
970
- int hdr_type, list_type, indent;
1118
+ int hdr_type, list_type, list_class, indent;
971
1119
 
972
1120
  ptr = consume(ptr, &para);
973
1121
 
@@ -990,13 +1138,19 @@ compile(Line *ptr, int toplevel, MMIOT *f)
990
1138
  ptr = ptr->next;
991
1139
  ___mkd_freeLine(r);
992
1140
  }
993
- else if (( list_type = islist(ptr, &indent) )) {
994
- p = Pp(&d, ptr, list_type);
995
- ptr = listblock(p, indent, f);
1141
+ else if (( list_class = islist(ptr, &indent, f->flags, &list_type) )) {
1142
+ if ( list_class == DL ) {
1143
+ p = Pp(&d, ptr, DL);
1144
+ ptr = definition_block(p, indent, f, list_type);
1145
+ }
1146
+ else {
1147
+ p = Pp(&d, ptr, list_type);
1148
+ ptr = enumerated_block(p, indent, f, list_class);
1149
+ }
996
1150
  }
997
1151
  else if ( isquote(ptr) ) {
998
1152
  p = Pp(&d, ptr, QUOTE);
999
- ptr = quoteblock(p);
1153
+ ptr = quoteblock(p, f->flags);
1000
1154
  p->down = compile(p->text, 1, f);
1001
1155
  p->text = 0;
1002
1156
  }
@@ -1004,13 +1158,13 @@ compile(Line *ptr, int toplevel, MMIOT *f)
1004
1158
  p = Pp(&d, ptr, HDR);
1005
1159
  ptr = headerblock(p, hdr_type);
1006
1160
  }
1007
- else if ( istable(ptr) && !(f->flags & (STRICT|NOTABLES)) ) {
1161
+ else if ( istable(ptr) && !(f->flags & (MKD_STRICT|MKD_NOTABLES)) ) {
1008
1162
  p = Pp(&d, ptr, TABLE);
1009
1163
  ptr = tableblock(p);
1010
1164
  }
1011
1165
  else {
1012
1166
  p = Pp(&d, ptr, MARKUP);
1013
- ptr = textblock(p, toplevel);
1167
+ ptr = textblock(p, toplevel, f->flags);
1014
1168
  }
1015
1169
 
1016
1170
  if ( (para||toplevel) && !p->align )
@@ -1028,19 +1182,6 @@ compile(Line *ptr, int toplevel, MMIOT *f)
1028
1182
  }
1029
1183
 
1030
1184
 
1031
- static void
1032
- initialize()
1033
- {
1034
- static int first = 1;
1035
-
1036
- if ( first-- > 0 ) {
1037
- first = 0;
1038
- INITRNG(time(0));
1039
- qsort(blocktags, SZTAGS, sizeof blocktags[0], (stfu)casort);
1040
- }
1041
- }
1042
-
1043
-
1044
1185
  /*
1045
1186
  * the guts of the markdown() function, ripped out so I can do
1046
1187
  * debugging.
@@ -1050,7 +1191,7 @@ initialize()
1050
1191
  * prepare and compile `text`, returning a Paragraph tree.
1051
1192
  */
1052
1193
  int
1053
- mkd_compile(Document *doc, int flags)
1194
+ mkd_compile(Document *doc, DWORD flags)
1054
1195
  {
1055
1196
  if ( !doc )
1056
1197
  return 0;
@@ -1060,13 +1201,13 @@ mkd_compile(Document *doc, int flags)
1060
1201
 
1061
1202
  doc->compiled = 1;
1062
1203
  memset(doc->ctx, 0, sizeof(MMIOT) );
1063
- doc->ctx->flags = flags & USER_FLAGS;
1064
- doc->ctx->base = doc->base;
1204
+ doc->ctx->cb = &(doc->cb);
1205
+ doc->ctx->flags = flags & USER_FLAGS;
1065
1206
  CREATE(doc->ctx->in);
1066
1207
  doc->ctx->footnotes = malloc(sizeof doc->ctx->footnotes[0]);
1067
1208
  CREATE(*doc->ctx->footnotes);
1068
1209
 
1069
- initialize();
1210
+ mkd_initialize();
1070
1211
 
1071
1212
  doc->code = compile_document(T(doc->content), doc->ctx);
1072
1213
  qsort(T(*doc->ctx->footnotes), S(*doc->ctx->footnotes),