bluecloth 2.0.7-x86-mswin32 → 2.0.11pre158-x86-mswin32

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.
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),