rdiscount 2.0.7.3 → 2.1.6

Sign up to get free protection for your applications and to get access to all the features.
data/BUILDING CHANGED
@@ -20,7 +20,7 @@ the rake gather task to copy discount source files into the ext/ directory:
20
20
  Submodule 'discount' (git://github.com/davidfstr/discount.git) registered for path 'discount'
21
21
  Cloning into discount...
22
22
  $ cd discount
23
- $ ./configure.sh # to generate mkdio.h from mkdio.h.in
23
+ $ ./configure.sh --with-fenced-code --with-github-tags
24
24
  $ cd ..
25
25
  $ rake gather
26
26
  $ rake build
@@ -49,7 +49,7 @@ Copy the new Discount sources to the appropriate directories for RDiscount:
49
49
  Update rdiscount.gemspec to include all *.c, *.h, and *.rb files in
50
50
  ext. This must be done manually. Here's a quick way to get the full list:
51
51
 
52
- $ echo ext/*.c ext/*.h ext/*.rb ext/VERSION | tr ' ' "\n" | sort
52
+ $ echo ext/*.c ext/*.h ext/*.rb ext/blocktags ext/VERSION | tr ' ' "\n" | sort
53
53
 
54
54
  Build the RDiscount gem. If you get errors related to missing files
55
55
  in ext, make sure you updated the gemspec correctly in the previous step.
@@ -92,7 +92,8 @@ release tests mentioned above.
92
92
 
93
93
  Update the CHANGELOG.
94
94
 
95
- Update rdiscount.gemspec with the new version number and date.
95
+ Update rdiscount.gemspec with the new RDiscount version number and date.
96
+ Also update the VERSION constant in lib/rdiscount.rb.
96
97
  Push that change as the final commit with a message in the format
97
98
  "2.0.7 release".
98
99
 
data/COPYING CHANGED
@@ -6,47 +6,28 @@ Copyright (C) 2008 Ryan Tomayko.
6
6
 
7
7
  All rights reserved.
8
8
 
9
- Permission is hereby granted, free of charge, to any person
10
- obtaining a copy of this software and associated documentation files
11
- (the "Software"), to deal in the Software without restriction,
12
- including without limitation the rights to use, copy, modify, merge,
13
- publish, distribute, sublicence, and/or sell copies of the Software,
14
- and to permit persons to whom the Software is furnished to do so,
15
- subject to the following conditions:
16
-
17
- 1. Redistributions of source code must retain the above copyright
18
- notice, this list of conditions, and the following disclaimer.
19
-
20
- 2. Redistributions in binary form must reproduce the above
21
- copyright notice, this list of conditions and the following
22
- disclaimer in the documentation and/or other materials provided
23
- with the distribution, and in the same place and form as other
24
- copyright, license and disclaimer information.
25
-
26
- 3. The end-user documentation included with the redistribution, if
27
- any, must include the following acknowledgment:
28
-
29
- This product includes software developed by
30
- David Loren Parsons <http://www.pell.portland.or.us/~orc>
31
-
32
- in the same place and form as other third-party acknowledgments.
33
- Alternately, this acknowledgment may appear in the software
34
- itself, in the same form and location as other such third-party
35
- acknowledgments.
36
-
37
- 4. Except as contained in this notice, the name of David Loren
38
- Parsons shall not be used in advertising or otherwise to promote
39
- the sale, use or other dealings in this Software without prior
40
- written authorization from David Loren Parsons.
41
-
42
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
43
- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
44
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
45
- IN NO EVENT SHALL DAVID LOREN PARSONS BE LIABLE FOR ANY DIRECT,
46
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
47
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
50
- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
52
- OF THE POSSIBILITY OF SUCH DAMAGE.
9
+ Redistribution and use in source and binary forms, with or without
10
+ modification, are permitted provided that the following conditions
11
+ are met:
12
+
13
+ 1. Redistributions of works must retain the original copyright notice,
14
+ this list of conditions and the following disclaimer.
15
+ 2. Redistributions in binary form must reproduce the original copyright
16
+ notice, this list of conditions and the following disclaimer in the
17
+ documentation and/or other materials provided with the distribution.
18
+ 3. Neither my name (David L Parsons) nor the names of contributors to
19
+ this code may be used to endorse or promote products derived
20
+ from this work without specific prior written permission.
21
+
22
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26
+ COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ POSSIBILITY OF SUCH DAMAGE.
data/Rakefile CHANGED
@@ -111,12 +111,14 @@ CLEAN.include 'doc'
111
111
 
112
112
  desc 'Gather required discount sources into extension directory'
113
113
  task :gather => 'discount/markdown.h' do |t|
114
+ # Files unique to /ext that should not be overridden
114
115
  rdiscount_ext_files = [
115
116
  "config.h",
116
117
  "extconf.rb",
117
118
  "rdiscount.c",
118
119
  ]
119
120
 
121
+ # Files in /discount that have a main function and should not be copied to /ext
120
122
  discount_c_files_with_main_function = [
121
123
  "main.c",
122
124
  "makepage.c",
@@ -152,6 +154,8 @@ task :gather => 'discount/markdown.h' do |t|
152
154
  :verbose => true
153
155
  end
154
156
 
157
+ # Copy special files from discount -> ext
158
+ cp 'discount/blocktags', 'ext/'
155
159
  cp 'discount/VERSION', 'ext/'
156
160
 
157
161
  # Copy man page
data/ext/Csio.c CHANGED
@@ -54,7 +54,7 @@ Csreparse(Cstring *iot, char *buf, int size, int flags)
54
54
  {
55
55
  MMIOT f;
56
56
  ___mkd_initmmiot(&f, 0);
57
- ___mkd_reparse(buf, size, 0, &f);
57
+ ___mkd_reparse(buf, size, 0, &f, 0);
58
58
  ___mkd_emblock(&f);
59
59
  SUFFIX(*iot, T(f.out), S(f.out));
60
60
  ___mkd_freemmiot(&f, 0);
data/ext/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.7
1
+ 2.1.6
data/ext/blocktags ADDED
@@ -0,0 +1,33 @@
1
+ static struct kw blocktags[] = {
2
+ { "P", 1, 0 },
3
+ { "DL", 2, 0 },
4
+ { "H1", 2, 0 },
5
+ { "H2", 2, 0 },
6
+ { "H3", 2, 0 },
7
+ { "H4", 2, 0 },
8
+ { "H5", 2, 0 },
9
+ { "H6", 2, 0 },
10
+ { "HR", 2, 1 },
11
+ { "OL", 2, 0 },
12
+ { "UL", 2, 0 },
13
+ { "BDO", 3, 0 },
14
+ { "DFN", 3, 0 },
15
+ { "DIV", 3, 0 },
16
+ { "MAP", 3, 0 },
17
+ { "PRE", 3, 0 },
18
+ { "WBR", 3, 0 },
19
+ { "XMP", 3, 0 },
20
+ { "NOBR", 4, 0 },
21
+ { "STYLE", 5, 0 },
22
+ { "TABLE", 5, 0 },
23
+ { "CENTER", 6, 0 },
24
+ { "IFRAME", 6, 0 },
25
+ { "OBJECT", 6, 0 },
26
+ { "SCRIPT", 6, 0 },
27
+ { "ADDRESS", 7, 0 },
28
+ { "LISTING", 7, 0 },
29
+ { "PLAINTEXT", 9, 0 },
30
+ { "BLOCKQUOTE", 10, 0 },
31
+ };
32
+
33
+ #define NR_blocktags 29
data/ext/config.h CHANGED
@@ -7,6 +7,12 @@
7
7
  /* tabs are four spaces */
8
8
  #define TABSTOP 4
9
9
 
10
+ /* enable fenced code blocks */
11
+ #define WITH_FENCED_CODE 1
12
+
13
+ /* include - and _ as acceptable characters in HTML tag names */
14
+ #define WITH_GITHUB_TAGS 1
15
+
10
16
  /* these are setup by extconf.rb */
11
17
  #if HAVE_RANDOM
12
18
  #define COINTOSS() (random()&1)
data/ext/cstring.h CHANGED
@@ -27,9 +27,9 @@
27
27
  #define DELETE(x) ALLOCATED(x) ? (free(T(x)), S(x) = (x).alloc = 0) \
28
28
  : ( S(x) = 0 )
29
29
  #define CLIP(t,i,sz) \
30
- ( ((i) >= 0) && ((sz) > 0) && (((i)+(sz)) <= S(t)) ) ? \
30
+ S(t) -= ( ((i) >= 0) && ((sz) > 0) && (((i)+(sz)) <= S(t)) ) ? \
31
31
  (memmove(&T(t)[i], &T(t)[i+sz], (S(t)-(i+sz)+1)*sizeof(T(t)[0])), \
32
- S(t) -= (sz)) : -1
32
+ (sz)) : 0
33
33
 
34
34
  #define RESERVE(x, sz) T(x) = ((x).alloc > S(x) + (sz) \
35
35
  ? T(x) \
data/ext/flags.c CHANGED
@@ -29,6 +29,7 @@ static struct flagnames flagnames[] = {
29
29
  { MKD_NOALPHALIST, "!ALPHALIST" },
30
30
  { MKD_NODLIST, "!DLIST" },
31
31
  { MKD_EXTRA_FOOTNOTE, "FOOTNOTE" },
32
+ { MKD_NOSTYLE, "!STYLE" },
32
33
  };
33
34
  #define NR(x) (sizeof x/sizeof x[0])
34
35
 
data/ext/generate.c CHANGED
@@ -40,7 +40,7 @@ push(char *bfr, int size, MMIOT *f)
40
40
 
41
41
  /* look <i> characters ahead of the cursor.
42
42
  */
43
- static int
43
+ static inline int
44
44
  peek(MMIOT *f, int i)
45
45
  {
46
46
 
@@ -52,7 +52,7 @@ peek(MMIOT *f, int i)
52
52
 
53
53
  /* pull a byte from the input buffer
54
54
  */
55
- static int
55
+ static inline int
56
56
  pull(MMIOT *f)
57
57
  {
58
58
  return ( f->isp < S(f->in) ) ? T(f->in)[f->isp++] : EOF;
@@ -61,23 +61,23 @@ pull(MMIOT *f)
61
61
 
62
62
  /* return a pointer to the current position in the input buffer.
63
63
  */
64
- static char*
64
+ static inline char*
65
65
  cursor(MMIOT *f)
66
66
  {
67
67
  return T(f->in) + f->isp;
68
68
  }
69
69
 
70
70
 
71
- static int
71
+ static inline int
72
72
  isthisspace(MMIOT *f, int i)
73
73
  {
74
74
  int c = peek(f, i);
75
75
 
76
- return isspace(c) || (c == EOF);
76
+ return isspace(c) || (c < ' ');
77
77
  }
78
78
 
79
79
 
80
- static int
80
+ static inline int
81
81
  isthisalnum(MMIOT *f, int i)
82
82
  {
83
83
  int c = peek(f, i);
@@ -86,7 +86,7 @@ isthisalnum(MMIOT *f, int i)
86
86
  }
87
87
 
88
88
 
89
- static int
89
+ static inline int
90
90
  isthisnonword(MMIOT *f, int i)
91
91
  {
92
92
  return isthisspace(f, i) || ispunct(peek(f,i));
@@ -183,9 +183,10 @@ Qem(MMIOT *f, char c, int count)
183
183
  /* generate html from a markup fragment
184
184
  */
185
185
  void
186
- ___mkd_reparse(char *bfr, int size, int flags, MMIOT *f)
186
+ ___mkd_reparse(char *bfr, int size, int flags, MMIOT *f, char *esc)
187
187
  {
188
188
  MMIOT sub;
189
+ struct escaped e;
189
190
 
190
191
  ___mkd_initmmiot(&sub, f->footnotes);
191
192
 
@@ -193,6 +194,14 @@ ___mkd_reparse(char *bfr, int size, int flags, MMIOT *f)
193
194
  sub.cb = f->cb;
194
195
  sub.ref_prefix = f->ref_prefix;
195
196
 
197
+ if ( esc ) {
198
+ sub.esc = &e;
199
+ e.up = f->esc;
200
+ e.text = esc;
201
+ }
202
+ else
203
+ sub.esc = f->esc;
204
+
196
205
  push(bfr, size, &sub);
197
206
  EXPAND(sub.in) = 0;
198
207
  S(sub.in)--;
@@ -206,6 +215,23 @@ ___mkd_reparse(char *bfr, int size, int flags, MMIOT *f)
206
215
  }
207
216
 
208
217
 
218
+ /*
219
+ * check the escape list for special cases
220
+ */
221
+ static int
222
+ escaped(MMIOT *f, char c)
223
+ {
224
+ struct escaped *thing = f->esc;
225
+
226
+ while ( thing ) {
227
+ if ( strchr(thing->text, c) )
228
+ return 1;
229
+ thing = thing->up;
230
+ }
231
+ return 0;
232
+ }
233
+
234
+
209
235
  /*
210
236
  * write out a url, escaping problematic characters
211
237
  */
@@ -553,7 +579,7 @@ printlinkyref(MMIOT *f, linkytype *tag, char *link, int size)
553
579
  puturl(link + tag->szpat, size - tag->szpat, f, 0);
554
580
  }
555
581
  else
556
- ___mkd_reparse(link + tag->szpat, size - tag->szpat, MKD_TAGTEXT, f);
582
+ ___mkd_reparse(link + tag->szpat, size - tag->szpat, MKD_TAGTEXT, f, 0);
557
583
 
558
584
  Qstring(tag->link_sfx, f);
559
585
 
@@ -585,7 +611,7 @@ extra_linky(MMIOT *f, Cstring text, Footnote *ref)
585
611
  return 0;
586
612
 
587
613
  if ( f->flags & IS_LABEL )
588
- ___mkd_reparse(T(text), S(text), linkt.flags, f);
614
+ ___mkd_reparse(T(text), S(text), linkt.flags, f, 0);
589
615
  else {
590
616
  ref->flags |= REFERENCED;
591
617
  ref->refnumber = ++ f->reference;
@@ -604,7 +630,8 @@ linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref)
604
630
  {
605
631
  linkytype *tag;
606
632
 
607
- if ( image || (ref == 0) )
633
+
634
+ if ( image )
608
635
  tag = &imaget;
609
636
  else if ( tag = pseudo(ref->link) ) {
610
637
  if ( f->flags & (MKD_NO_EXT|MKD_SAFELINK) )
@@ -624,7 +651,7 @@ linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref)
624
651
  return 0;
625
652
 
626
653
  if ( f->flags & IS_LABEL )
627
- ___mkd_reparse(T(text), S(text), tag->flags, f);
654
+ ___mkd_reparse(T(text), S(text), tag->flags, f, 0);
628
655
  else if ( tag->link_pfx ) {
629
656
  printlinkyref(f, tag, T(ref->link), S(ref->link));
630
657
 
@@ -635,12 +662,12 @@ linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref)
635
662
 
636
663
  if ( S(ref->title) ) {
637
664
  Qstring(" title=\"", f);
638
- ___mkd_reparse(T(ref->title), S(ref->title), MKD_TAGTEXT, f);
665
+ ___mkd_reparse(T(ref->title), S(ref->title), MKD_TAGTEXT, f, 0);
639
666
  Qchar('"', f);
640
667
  }
641
668
 
642
669
  Qstring(tag->text_pfx, f);
643
- ___mkd_reparse(T(text), S(text), tag->flags, f);
670
+ ___mkd_reparse(T(text), S(text), tag->flags, f, 0);
644
671
  Qstring(tag->text_sfx, f);
645
672
  }
646
673
  else
@@ -707,8 +734,6 @@ linkylinky(int image, MMIOT *f)
707
734
  else
708
735
  status = linkyformat(f, name, image, ref);
709
736
  }
710
- else if ( f->flags & IS_LABEL )
711
- status = linkyformat(f, name, image, 0);
712
737
  }
713
738
  }
714
739
  }
@@ -810,6 +835,8 @@ code(MMIOT *f, char *s, int length)
810
835
  for ( i=0; i < length; i++ )
811
836
  if ( (c = s[i]) == 003) /* ^C: expand back to 2 spaces */
812
837
  Qstring(" ", f);
838
+ else if ( c == '\\' && (i < length-1) && escaped(f, s[i+1]) )
839
+ cputc(s[++i], f);
813
840
  else
814
841
  cputc(c, f);
815
842
  } /* code */
@@ -821,7 +848,7 @@ static void
821
848
  delspan(MMIOT *f, int size)
822
849
  {
823
850
  Qstring("<del>", f);
824
- ___mkd_reparse(cursor(f)-1, size, 0, f);
851
+ ___mkd_reparse(cursor(f)-1, size, 0, f, 0);
825
852
  Qstring("</del>", f);
826
853
  }
827
854
 
@@ -963,7 +990,11 @@ maybe_tag_or_link(MMIOT *f)
963
990
  }
964
991
  else if ( isspace(c) )
965
992
  break;
993
+ #if WITH_GITHUB_TAGS
994
+ else if ( ! (c == '/' || c == '-' || c == '_' || isalnum(c) ) )
995
+ #else
966
996
  else if ( ! (c == '/' || isalnum(c) ) )
997
+ #endif
967
998
  maybetag=0;
968
999
  }
969
1000
 
@@ -1054,7 +1085,7 @@ islike(MMIOT *f, char *s)
1054
1085
  int len;
1055
1086
  int i;
1056
1087
 
1057
- if ( s[0] == '<' ) {
1088
+ if ( s[0] == '|' ) {
1058
1089
  if ( !isthisnonword(f, -1) )
1059
1090
  return 0;
1060
1091
  ++s;
@@ -1063,7 +1094,7 @@ islike(MMIOT *f, char *s)
1063
1094
  if ( !(len = strlen(s)) )
1064
1095
  return 0;
1065
1096
 
1066
- if ( s[len-1] == '>' ) {
1097
+ if ( s[len-1] == '|' ) {
1067
1098
  if ( !isthisnonword(f,len-1) )
1068
1099
  return 0;
1069
1100
  len--;
@@ -1082,25 +1113,25 @@ static struct smarties {
1082
1113
  char *entity;
1083
1114
  int shift;
1084
1115
  } smarties[] = {
1085
- { '\'', "'s>", "rsquo", 0 },
1086
- { '\'', "'t>", "rsquo", 0 },
1087
- { '\'', "'re>", "rsquo", 0 },
1088
- { '\'', "'ll>", "rsquo", 0 },
1089
- { '\'', "'ve>", "rsquo", 0 },
1090
- { '\'', "'m>", "rsquo", 0 },
1091
- { '\'', "'d>", "rsquo", 0 },
1092
- { '-', "--", "mdash", 1 },
1093
- { '-', "<->", "ndash", 0 },
1116
+ { '\'', "'s|", "rsquo", 0 },
1117
+ { '\'', "'t|", "rsquo", 0 },
1118
+ { '\'', "'re|", "rsquo", 0 },
1119
+ { '\'', "'ll|", "rsquo", 0 },
1120
+ { '\'', "'ve|", "rsquo", 0 },
1121
+ { '\'', "'m|", "rsquo", 0 },
1122
+ { '\'', "'d|", "rsquo", 0 },
1123
+ { '-', "---", "mdash", 2 },
1124
+ { '-', "--", "ndash", 1 },
1094
1125
  { '.', "...", "hellip", 2 },
1095
1126
  { '.', ". . .", "hellip", 4 },
1096
1127
  { '(', "(c)", "copy", 2 },
1097
1128
  { '(', "(r)", "reg", 2 },
1098
1129
  { '(', "(tm)", "trade", 3 },
1099
- { '3', "<3/4>", "frac34", 2 },
1100
- { '3', "<3/4ths>", "frac34", 2 },
1101
- { '1', "<1/2>", "frac12", 2 },
1102
- { '1', "<1/4>", "frac14", 2 },
1103
- { '1', "<1/4th>", "frac14", 2 },
1130
+ { '3', "|3/4|", "frac34", 2 },
1131
+ { '3', "|3/4ths|", "frac34", 2 },
1132
+ { '1', "|1/2|", "frac12", 2 },
1133
+ { '1', "|1/4|", "frac14", 2 },
1134
+ { '1', "|1/4th|", "frac14", 2 },
1104
1135
  { '&', "&#0;", 0, 3 },
1105
1136
  } ;
1106
1137
  #define NRSMART ( sizeof smarties / sizeof smarties[0] )
@@ -1142,7 +1173,7 @@ smartypants(int c, int *flags, MMIOT *f)
1142
1173
  break;
1143
1174
  else if ( c == '\'' && peek(f, j+1) == '\'' ) {
1144
1175
  Qstring("&ldquo;", f);
1145
- ___mkd_reparse(cursor(f)+1, j-2, 0, f);
1176
+ ___mkd_reparse(cursor(f)+1, j-2, 0, f, 0);
1146
1177
  Qstring("&rdquo;", f);
1147
1178
  shift(f,j+1);
1148
1179
  return 1;
@@ -1162,11 +1193,14 @@ smartypants(int c, int *flags, MMIOT *f)
1162
1193
  * let the caller figure it out.
1163
1194
  */
1164
1195
  static int
1165
- tickhandler(MMIOT *f, int tickchar, int minticks, spanhandler spanner)
1196
+ tickhandler(MMIOT *f, int tickchar, int minticks, int allow_space, spanhandler spanner)
1166
1197
  {
1167
1198
  int endticks, size;
1168
1199
  int tick = nrticks(0, tickchar, f);
1169
1200
 
1201
+ if ( !allow_space && isspace(peek(f,tick)) )
1202
+ return 0;
1203
+
1170
1204
  if ( (tick >= minticks) && (size = matchticks(f,tickchar,tick,&endticks)) ) {
1171
1205
  if ( endticks < tick ) {
1172
1206
  size += (tick - endticks);
@@ -1261,7 +1295,7 @@ text(MMIOT *f)
1261
1295
  shift(f,len);
1262
1296
  }
1263
1297
  Qstring("<sup>",f);
1264
- ___mkd_reparse(sup, len, 0, f);
1298
+ ___mkd_reparse(sup, len, 0, f, "()");
1265
1299
  Qstring("</sup>", f);
1266
1300
  }
1267
1301
  break;
@@ -1290,18 +1324,27 @@ text(MMIOT *f)
1290
1324
  }
1291
1325
  break;
1292
1326
 
1293
- case '~': if ( (f->flags & (MKD_NOSTRIKETHROUGH|MKD_TAGTEXT|MKD_STRICT)) || !tickhandler(f,c,2,delspan) )
1327
+ case '~': if ( (f->flags & (MKD_NOSTRIKETHROUGH|MKD_TAGTEXT|MKD_STRICT)) || ! tickhandler(f,c,2,0, delspan) )
1294
1328
  Qchar(c, f);
1295
1329
  break;
1296
1330
 
1297
- case '`': if ( tag_text(f) || !tickhandler(f,c,1,codespan) )
1331
+ case '`': if ( tag_text(f) || !tickhandler(f,c,1,1,codespan) )
1298
1332
  Qchar(c, f);
1299
1333
  break;
1300
1334
 
1301
1335
  case '\\': switch ( c = pull(f) ) {
1302
1336
  case '&': Qstring("&amp;", f);
1303
1337
  break;
1304
- case '<': Qstring("&lt;", f);
1338
+ case '<': c = peek(f,1);
1339
+ if ( (c == EOF) || isspace(c) )
1340
+ Qstring("&lt;", f);
1341
+ else {
1342
+ /* Markdown.pl does not escape <[nonwhite]
1343
+ * sequences */
1344
+ Qchar('\\', f);
1345
+ shift(f, -1);
1346
+ }
1347
+
1305
1348
  break;
1306
1349
  case '^': if ( f->flags & (MKD_STRICT|MKD_NOSUPERSCRIPT) ) {
1307
1350
  Qchar('\\', f);
@@ -1311,16 +1354,25 @@ text(MMIOT *f)
1311
1354
  Qchar(c, f);
1312
1355
  break;
1313
1356
 
1314
- case '>': case '#': case '.': case '-':
1315
- case '+': case '{': case '}': case ']':
1316
- case '!': case '[': case '*': case '_':
1317
- case '\\':case '(': case ')':
1318
- case '`': Qchar(c, f);
1319
- break;
1320
- default:
1321
- Qchar('\\', f);
1322
- if ( c != EOF )
1357
+ case ':': case '|':
1358
+ if ( f->flags & MKD_NOTABLES ) {
1359
+ Qchar('\\', f);
1323
1360
  shift(f,-1);
1361
+ break;
1362
+ }
1363
+ Qchar(c, f);
1364
+ break;
1365
+
1366
+ case EOF: Qchar('\\', f);
1367
+ break;
1368
+
1369
+ default: if ( escaped(f,c) ||
1370
+ strchr(">#.-+{}]![*_\\()`", c) )
1371
+ Qchar(c, f);
1372
+ else {
1373
+ Qchar('\\', f);
1374
+ shift(f, -1);
1375
+ }
1324
1376
  break;
1325
1377
  }
1326
1378
  break;
@@ -1353,6 +1405,17 @@ text(MMIOT *f)
1353
1405
  static void
1354
1406
  printheader(Paragraph *pp, MMIOT *f)
1355
1407
  {
1408
+ #if WITH_ID_ANCHOR
1409
+ Qprintf(f, "<h%d", pp->hnumber);
1410
+ if ( f->flags & MKD_TOC ) {
1411
+ Qstring(" id=\"", f);
1412
+ mkd_string_to_anchor(T(pp->text->text),
1413
+ S(pp->text->text),
1414
+ (mkd_sta_function_t)Qchar, f, 1);
1415
+ Qchar('"', f);
1416
+ }
1417
+ Qchar('>', f);
1418
+ #else
1356
1419
  if ( f->flags & MKD_TOC ) {
1357
1420
  Qstring("<a name=\"", f);
1358
1421
  mkd_string_to_anchor(T(pp->text->text),
@@ -1361,6 +1424,7 @@ printheader(Paragraph *pp, MMIOT *f)
1361
1424
  Qstring("\"></a>\n", f);
1362
1425
  }
1363
1426
  Qprintf(f, "<h%d>", pp->hnumber);
1427
+ #endif
1364
1428
  push(T(pp->text->text), S(pp->text->text), f);
1365
1429
  text(f);
1366
1430
  Qprintf(f, "</h%d>", pp->hnumber);
@@ -1369,8 +1433,9 @@ printheader(Paragraph *pp, MMIOT *f)
1369
1433
 
1370
1434
  enum e_alignments { a_NONE, a_CENTER, a_LEFT, a_RIGHT };
1371
1435
 
1372
- static char* alignments[] = { "", " align=\"center\"", " align=\"left\"",
1373
- " align=\"right\"" };
1436
+ static char* alignments[] = { "", " style=\"text-align:center;\"",
1437
+ " style=\"text-align:left;\"",
1438
+ " style=\"text-align:right;\"" };
1374
1439
 
1375
1440
  typedef STRING(int) Istring;
1376
1441
 
@@ -1378,22 +1443,30 @@ static int
1378
1443
  splat(Line *p, char *block, Istring align, int force, MMIOT *f)
1379
1444
  {
1380
1445
  int first,
1381
- idx = 0,
1446
+ idx = p->dle,
1382
1447
  colno = 0;
1383
1448
 
1449
+
1450
+ ___mkd_tidy(&p->text);
1451
+ if ( T(p->text)[S(p->text)-1] == '|' )
1452
+ --S(p->text);
1453
+
1384
1454
  Qstring("<tr>\n", f);
1385
1455
  while ( idx < S(p->text) ) {
1386
1456
  first = idx;
1387
1457
  if ( force && (colno >= S(align)-1) )
1388
1458
  idx = S(p->text);
1389
1459
  else
1390
- while ( (idx < S(p->text)) && (T(p->text)[idx] != '|') )
1460
+ while ( (idx < S(p->text)) && (T(p->text)[idx] != '|') ) {
1461
+ if ( T(p->text)[idx] == '\\' )
1462
+ ++idx;
1391
1463
  ++idx;
1464
+ }
1392
1465
 
1393
1466
  Qprintf(f, "<%s%s>",
1394
1467
  block,
1395
1468
  alignments[ (colno < S(align)) ? T(align)[colno] : a_NONE ]);
1396
- ___mkd_reparse(T(p->text)+first, idx-first, 0, f);
1469
+ ___mkd_reparse(T(p->text)+first, idx-first, 0, f, "|");
1397
1470
  Qprintf(f, "</%s>\n", block);
1398
1471
  idx++;
1399
1472
  colno++;
@@ -1415,34 +1488,43 @@ printtable(Paragraph *pp, MMIOT *f)
1415
1488
 
1416
1489
  Line *hdr, *dash, *body;
1417
1490
  Istring align;
1418
- int start;
1419
- int hcols;
1491
+ int hcols,start;
1420
1492
  char *p;
1421
-
1422
- if ( !(pp->text && pp->text->next) )
1423
- return 0;
1493
+ enum e_alignments it;
1424
1494
 
1425
1495
  hdr = pp->text;
1426
1496
  dash= hdr->next;
1427
1497
  body= dash->next;
1428
1498
 
1429
- /* first figure out cell alignments */
1499
+ if ( T(hdr->text)[hdr->dle] == '|' ) {
1500
+ /* trim leading pipe off all lines
1501
+ */
1502
+ Line *r;
1503
+ for ( r = pp->text; r; r = r->next )
1504
+ r->dle ++;
1505
+ }
1506
+
1507
+ /* figure out cell alignments */
1430
1508
 
1431
1509
  CREATE(align);
1432
1510
 
1433
- for (p=T(dash->text), start=0; start < S(dash->text); ) {
1511
+ for (p=T(dash->text), start=dash->dle; start < S(dash->text); ) {
1434
1512
  char first, last;
1435
1513
  int end;
1436
1514
 
1437
1515
  last=first=0;
1438
1516
  for (end=start ; (end < S(dash->text)) && p[end] != '|'; ++ end ) {
1439
- if ( !isspace(p[end]) ) {
1517
+ if ( p[end] == '\\' )
1518
+ ++ end;
1519
+ else if ( !isspace(p[end]) ) {
1440
1520
  if ( !first) first = p[end];
1441
1521
  last = p[end];
1442
1522
  }
1443
1523
  }
1444
- EXPAND(align) = ( first == ':' ) ? (( last == ':') ? a_CENTER : a_LEFT)
1445
- : (( last == ':') ? a_RIGHT : a_NONE );
1524
+ it = ( first == ':' ) ? (( last == ':') ? a_CENTER : a_LEFT)
1525
+ : (( last == ':') ? a_RIGHT : a_NONE );
1526
+
1527
+ EXPAND(align) = it;
1446
1528
  start = 1+end;
1447
1529
  }
1448
1530
 
@@ -1568,7 +1650,7 @@ definitionlist(Paragraph *p, MMIOT *f)
1568
1650
  for ( ; p ; p = p->next) {
1569
1651
  for ( tag = p->text; tag; tag = tag->next ) {
1570
1652
  Qstring("<dt>", f);
1571
- ___mkd_reparse(T(tag->text), S(tag->text), 0, f);
1653
+ ___mkd_reparse(T(tag->text), S(tag->text), 0, f, 0);
1572
1654
  Qstring("</dt>\n", f);
1573
1655
  }
1574
1656