rdiscount 1.5.8.1 → 1.6.3
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.
- data/Rakefile +1 -1
- data/ext/basename.c +43 -0
- data/ext/emmatch.c +188 -0
- data/ext/generate.c +172 -237
- data/ext/markdown.c +34 -20
- data/ext/markdown.h +13 -2
- data/ext/mkdio.c +40 -8
- data/ext/mkdio.h +10 -0
- data/lib/rdiscount.rb +1 -1
- data/rdiscount.gemspec +3 -1
- data/test/markdown_test.rb +1 -1
- metadata +5 -4
data/Rakefile
CHANGED
@@ -100,7 +100,7 @@ task :gather => 'discount' do |t|
|
|
100
100
|
files =
|
101
101
|
FileList[
|
102
102
|
'discount/{markdown,mkdio,amalloc,cstring}.h',
|
103
|
-
'discount/{markdown,docheader,dumptree,generate,mkdio,resource,toc,Csio,xml,css}.c'
|
103
|
+
'discount/{markdown,docheader,dumptree,generate,mkdio,resource,toc,Csio,xml,css,basename,emmatch}.c'
|
104
104
|
]
|
105
105
|
cp files, 'ext/',
|
106
106
|
:preserve => true,
|
data/ext/basename.c
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
/*
|
2
|
+
* mkdio -- markdown front end input functions
|
3
|
+
*
|
4
|
+
* Copyright (C) 2007 David L Parsons.
|
5
|
+
* The redistribution terms are provided in the COPYRIGHT file that must
|
6
|
+
* be distributed with this source code.
|
7
|
+
*/
|
8
|
+
#include "config.h"
|
9
|
+
#include <stdio.h>
|
10
|
+
#include <stdlib.h>
|
11
|
+
#include <ctype.h>
|
12
|
+
|
13
|
+
#include "mkdio.h"
|
14
|
+
#include "cstring.h"
|
15
|
+
#include "amalloc.h"
|
16
|
+
|
17
|
+
static char *
|
18
|
+
e_basename(const char *string, const int size, void *context)
|
19
|
+
{
|
20
|
+
char *ret;
|
21
|
+
char *base = (char*)context;
|
22
|
+
|
23
|
+
if ( base && string && (*string == '/') && (ret=malloc(strlen(base)+size+2)) ) {
|
24
|
+
strcpy(ret, base);
|
25
|
+
strncat(ret, string, size);
|
26
|
+
return ret;
|
27
|
+
}
|
28
|
+
return 0;
|
29
|
+
}
|
30
|
+
|
31
|
+
static void
|
32
|
+
e_free(char *string, void *context)
|
33
|
+
{
|
34
|
+
if ( string ) free(string);
|
35
|
+
}
|
36
|
+
|
37
|
+
void
|
38
|
+
mkd_basename(MMIOT *document, char *base)
|
39
|
+
{
|
40
|
+
mkd_e_url(document, e_basename);
|
41
|
+
mkd_e_data(document, base);
|
42
|
+
mkd_e_free(document, e_free);
|
43
|
+
}
|
data/ext/emmatch.c
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
/* markdown: a C implementation of John Gruber's Markdown markup language.
|
2
|
+
*
|
3
|
+
* Copyright (C) 2010 David L Parsons.
|
4
|
+
* The redistribution terms are provided in the COPYRIGHT file that must
|
5
|
+
* be distributed with this source code.
|
6
|
+
*/
|
7
|
+
#include <stdio.h>
|
8
|
+
#include <string.h>
|
9
|
+
#include <stdarg.h>
|
10
|
+
#include <stdlib.h>
|
11
|
+
#include <time.h>
|
12
|
+
#include <ctype.h>
|
13
|
+
|
14
|
+
#include "config.h"
|
15
|
+
|
16
|
+
#include "cstring.h"
|
17
|
+
#include "markdown.h"
|
18
|
+
#include "amalloc.h"
|
19
|
+
|
20
|
+
|
21
|
+
/* emmatch: the emphasis mangler that's run after a block
|
22
|
+
* of html has been generated.
|
23
|
+
*
|
24
|
+
* It should create MarkdownTest_1.0 (and _1.0.3)
|
25
|
+
* compatable emphasis for non-pathological cases
|
26
|
+
* and it should fail in a standards-compliant way
|
27
|
+
* when someone attempts to feed it junk.
|
28
|
+
*
|
29
|
+
* Emmatching is done after the input has been
|
30
|
+
* processed into a STRING (f->Q) of text and
|
31
|
+
* emphasis blocks. After ___mkd_emblock() finishes,
|
32
|
+
* it truncates f->Q and leaves the rendered paragraph
|
33
|
+
* if f->out.
|
34
|
+
*/
|
35
|
+
|
36
|
+
|
37
|
+
/* empair() -- find the NEAREST matching emphasis token (or
|
38
|
+
* subtoken of a 3+ long emphasis token.
|
39
|
+
*/
|
40
|
+
static int
|
41
|
+
empair(MMIOT *f, int first, int last, int match)
|
42
|
+
{
|
43
|
+
|
44
|
+
int i;
|
45
|
+
block *begin, *p;
|
46
|
+
|
47
|
+
begin = &T(f->Q)[first];
|
48
|
+
|
49
|
+
for (i=first+1; i <= last; i++) {
|
50
|
+
p = &T(f->Q)[i];
|
51
|
+
|
52
|
+
if ( (p->b_type != bTEXT) && (p->b_count <= 0) )
|
53
|
+
continue; /* break? */
|
54
|
+
|
55
|
+
if ( p->b_type == begin->b_type ) {
|
56
|
+
if ( p->b_count == match ) /* exact match */
|
57
|
+
return i;
|
58
|
+
|
59
|
+
if ( p->b_count > 2 ) /* fuzzy match */
|
60
|
+
return i;
|
61
|
+
}
|
62
|
+
}
|
63
|
+
return 0;
|
64
|
+
} /* empair */
|
65
|
+
|
66
|
+
|
67
|
+
/* emfill() -- if an emphasis token has leftover stars or underscores,
|
68
|
+
* convert them back into character and append them to b_text.
|
69
|
+
*/
|
70
|
+
static void
|
71
|
+
emfill(block *p)
|
72
|
+
{
|
73
|
+
int j;
|
74
|
+
|
75
|
+
if ( p->b_type == bTEXT )
|
76
|
+
return;
|
77
|
+
|
78
|
+
for (j=0; j < p->b_count; j++)
|
79
|
+
EXPAND(p->b_text) = p->b_char;
|
80
|
+
p->b_count = 0;
|
81
|
+
} /* emfill */
|
82
|
+
|
83
|
+
|
84
|
+
static void
|
85
|
+
emclose(MMIOT *f, int first, int last)
|
86
|
+
{
|
87
|
+
int j;
|
88
|
+
|
89
|
+
for (j=first+1; j<last-1; j++)
|
90
|
+
emfill(&T(f->Q)[j]);
|
91
|
+
}
|
92
|
+
|
93
|
+
|
94
|
+
static struct emtags {
|
95
|
+
char open[10];
|
96
|
+
char close[10];
|
97
|
+
int size;
|
98
|
+
} emtags[] = { { "<em>" , "</em>", 5 }, { "<strong>", "</strong>", 9 } };
|
99
|
+
|
100
|
+
|
101
|
+
static void emblock(MMIOT*,int,int);
|
102
|
+
|
103
|
+
|
104
|
+
/* emmatch() -- match emphasis for a single emphasis token.
|
105
|
+
*/
|
106
|
+
static void
|
107
|
+
emmatch(MMIOT *f, int first, int last)
|
108
|
+
{
|
109
|
+
block *start = &T(f->Q)[first];
|
110
|
+
int e, e2, match;
|
111
|
+
|
112
|
+
switch (start->b_count) {
|
113
|
+
case 2: if ( e = empair(f,first,last,match=2) )
|
114
|
+
break;
|
115
|
+
case 1: e = empair(f,first,last,match=1);
|
116
|
+
break;
|
117
|
+
case 0: return;
|
118
|
+
default:
|
119
|
+
e = empair(f,first,last,1);
|
120
|
+
e2= empair(f,first,last,2);
|
121
|
+
|
122
|
+
if ( e2 >= e ) {
|
123
|
+
e = e2;
|
124
|
+
match = 2;
|
125
|
+
}
|
126
|
+
else
|
127
|
+
match = 1;
|
128
|
+
break;
|
129
|
+
}
|
130
|
+
|
131
|
+
if ( e ) {
|
132
|
+
/* if we found emphasis to match, match it, recursively call
|
133
|
+
* emblock to match emphasis inside the new html block, add
|
134
|
+
* the emphasis markers for the block, then (tail) recursively
|
135
|
+
* call ourself to match any remaining emphasis on this token.
|
136
|
+
*/
|
137
|
+
block *end = &T(f->Q)[e];
|
138
|
+
|
139
|
+
end->b_count -= match;
|
140
|
+
start->b_count -= match;
|
141
|
+
|
142
|
+
emblock(f, first, e);
|
143
|
+
|
144
|
+
PREFIX(start->b_text, emtags[match-1].open, emtags[match-1].size-1);
|
145
|
+
SUFFIX(end->b_post, emtags[match-1].close, emtags[match-1].size);
|
146
|
+
|
147
|
+
emmatch(f, first, last);
|
148
|
+
}
|
149
|
+
} /* emmatch */
|
150
|
+
|
151
|
+
|
152
|
+
/* emblock() -- walk a blocklist, attempting to match emphasis
|
153
|
+
*/
|
154
|
+
static void
|
155
|
+
emblock(MMIOT *f, int first, int last)
|
156
|
+
{
|
157
|
+
int i;
|
158
|
+
|
159
|
+
for ( i = first; i <= last; i++ )
|
160
|
+
if ( T(f->Q)[i].b_type != bTEXT )
|
161
|
+
emmatch(f, i, last);
|
162
|
+
emclose(f, first, last);
|
163
|
+
} /* emblock */
|
164
|
+
|
165
|
+
|
166
|
+
/* ___mkd_emblock() -- emblock a string of blocks, then concatinate the
|
167
|
+
* resulting text onto f->out.
|
168
|
+
*/
|
169
|
+
void
|
170
|
+
___mkd_emblock(MMIOT *f)
|
171
|
+
{
|
172
|
+
int i;
|
173
|
+
block *p;
|
174
|
+
|
175
|
+
emblock(f, 0, S(f->Q)-1);
|
176
|
+
|
177
|
+
for (i=0; i < S(f->Q); i++) {
|
178
|
+
p = &T(f->Q)[i];
|
179
|
+
emfill(p);
|
180
|
+
|
181
|
+
if ( S(p->b_post) ) { SUFFIX(f->out, T(p->b_post), S(p->b_post));
|
182
|
+
DELETE(p->b_post); }
|
183
|
+
if ( S(p->b_text) ) { SUFFIX(f->out, T(p->b_text), S(p->b_text));
|
184
|
+
DELETE(p->b_text); }
|
185
|
+
}
|
186
|
+
|
187
|
+
S(f->Q) = 0;
|
188
|
+
} /* ___mkd_emblock */
|
data/ext/generate.c
CHANGED
@@ -21,8 +21,6 @@ typedef int (*stfu)(const void*,const void*);
|
|
21
21
|
|
22
22
|
|
23
23
|
/* forward declarations */
|
24
|
-
static int iscodeblock(MMIOT*);
|
25
|
-
static void code(int, MMIOT*);
|
26
24
|
static void text(MMIOT *f);
|
27
25
|
static Paragraph *display(Paragraph*, MMIOT*);
|
28
26
|
|
@@ -166,6 +164,16 @@ Qprintf(MMIOT *f, char *fmt, ...)
|
|
166
164
|
}
|
167
165
|
|
168
166
|
|
167
|
+
/* Qcopy()
|
168
|
+
*/
|
169
|
+
static void
|
170
|
+
Qcopy(int count, MMIOT *f)
|
171
|
+
{
|
172
|
+
while ( count-- > 0 )
|
173
|
+
Qchar(pull(f), f);
|
174
|
+
}
|
175
|
+
|
176
|
+
|
169
177
|
/* Qem()
|
170
178
|
*/
|
171
179
|
static void
|
@@ -182,118 +190,6 @@ Qem(MMIOT *f, char c, int count)
|
|
182
190
|
}
|
183
191
|
|
184
192
|
|
185
|
-
/* empair()
|
186
|
-
*/
|
187
|
-
static int
|
188
|
-
empair(MMIOT *f, int go, int level)
|
189
|
-
{
|
190
|
-
|
191
|
-
int i;
|
192
|
-
block *begin, *p;
|
193
|
-
|
194
|
-
begin = &T(f->Q)[go];
|
195
|
-
for (i=go+1; i < S(f->Q); i++) {
|
196
|
-
p = &T(f->Q)[i];
|
197
|
-
|
198
|
-
if ( (p->b_type != bTEXT) && (p->b_count <= 0) )
|
199
|
-
break;
|
200
|
-
|
201
|
-
if ( p->b_type == begin->b_type ) {
|
202
|
-
if ( p->b_count == level ) /* exact match */
|
203
|
-
return i-go;
|
204
|
-
|
205
|
-
if ( p->b_count > 2 ) /* fuzzy match */
|
206
|
-
return i-go;
|
207
|
-
}
|
208
|
-
}
|
209
|
-
return EOF;
|
210
|
-
}
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
static struct emtags {
|
215
|
-
char open[10];
|
216
|
-
char close[10];
|
217
|
-
int size;
|
218
|
-
} emtags[] = { { "<em>" , "</em>", 5 }, { "<strong>", "</strong>", 9 } };
|
219
|
-
|
220
|
-
|
221
|
-
static void
|
222
|
-
emclose(Cstring *s, int level)
|
223
|
-
{
|
224
|
-
PREFIX(*s, emtags[level-1].close, emtags[level-1].size);
|
225
|
-
}
|
226
|
-
|
227
|
-
|
228
|
-
static void
|
229
|
-
emopen(Cstring *s, int level)
|
230
|
-
{
|
231
|
-
SUFFIX(*s, emtags[level-1].open, emtags[level-1].size-1);
|
232
|
-
}
|
233
|
-
|
234
|
-
|
235
|
-
/* emmatch()
|
236
|
-
*/
|
237
|
-
static void
|
238
|
-
emmatch(MMIOT *f, int go)
|
239
|
-
{
|
240
|
-
block *start = &T(f->Q)[go], *end;
|
241
|
-
int e, e2, i, match;
|
242
|
-
|
243
|
-
while ( start->b_count ) {
|
244
|
-
switch (start->b_count) {
|
245
|
-
case 2: e = empair(f,go,match=2);
|
246
|
-
if ( e != EOF ) break;
|
247
|
-
case 1: e = empair(f,go,match=1); break;
|
248
|
-
default:
|
249
|
-
e = empair(f,go,1);
|
250
|
-
e2= empair(f,go,2);
|
251
|
-
|
252
|
-
if ( e == EOF || ((e2 != EOF) && (e2 >= e)) ) {
|
253
|
-
e = e2;
|
254
|
-
match = 2;
|
255
|
-
}
|
256
|
-
else
|
257
|
-
match = 1;
|
258
|
-
}
|
259
|
-
if ( e != EOF ) {
|
260
|
-
end = &T(f->Q)[go+e];
|
261
|
-
emclose(&end->b_post, match);
|
262
|
-
emopen(&start->b_text, match);
|
263
|
-
end->b_count -= match;
|
264
|
-
}
|
265
|
-
else {
|
266
|
-
for (i=0; i < match; i++)
|
267
|
-
EXPAND(start->b_text) = start->b_char;
|
268
|
-
}
|
269
|
-
|
270
|
-
start->b_count -= match;
|
271
|
-
}
|
272
|
-
}
|
273
|
-
|
274
|
-
|
275
|
-
/* ___mkd_emblock()
|
276
|
-
*/
|
277
|
-
void
|
278
|
-
___mkd_emblock(MMIOT *f)
|
279
|
-
{
|
280
|
-
int i;
|
281
|
-
block *p;
|
282
|
-
|
283
|
-
for (i=0; i < S(f->Q); i++) {
|
284
|
-
p = &T(f->Q)[i];
|
285
|
-
|
286
|
-
if ( p->b_type != bTEXT ) emmatch(f, i);
|
287
|
-
|
288
|
-
if ( S(p->b_post) ) { SUFFIX(f->out, T(p->b_post), S(p->b_post));
|
289
|
-
DELETE(p->b_post); }
|
290
|
-
if ( S(p->b_text) ) { SUFFIX(f->out, T(p->b_text), S(p->b_text));
|
291
|
-
DELETE(p->b_text); }
|
292
|
-
}
|
293
|
-
S(f->Q) = 0;
|
294
|
-
}
|
295
|
-
|
296
|
-
|
297
193
|
/* generate html from a markup fragment
|
298
194
|
*/
|
299
195
|
void
|
@@ -304,7 +200,7 @@ ___mkd_reparse(char *bfr, int size, int flags, MMIOT *f)
|
|
304
200
|
___mkd_initmmiot(&sub, f->footnotes);
|
305
201
|
|
306
202
|
sub.flags = f->flags | flags;
|
307
|
-
sub.
|
203
|
+
sub.cb = f->cb;
|
308
204
|
|
309
205
|
push(bfr, size, &sub);
|
310
206
|
EXPAND(sub.in) = 0;
|
@@ -345,6 +241,8 @@ puturl(char *s, int size, MMIOT *f, int display)
|
|
345
241
|
Qstring("%22", f);
|
346
242
|
else if ( isalnum(c) || ispunct(c) || (display && isspace(c)) )
|
347
243
|
Qchar(c, f);
|
244
|
+
else if ( c == 003 ) /* untokenize ^C */
|
245
|
+
Qstring(" ", f);
|
348
246
|
else
|
349
247
|
Qprintf(f, "%%%02X", c);
|
350
248
|
}
|
@@ -512,27 +410,28 @@ linkyurl(MMIOT *f, int image, Footnote *p)
|
|
512
410
|
|
513
411
|
/* prefixes for <automatic links>
|
514
412
|
*/
|
515
|
-
static struct {
|
413
|
+
static struct _protocol {
|
516
414
|
char *name;
|
517
415
|
int nlen;
|
518
416
|
} protocol[] = {
|
519
417
|
#define _aprotocol(x) { x, (sizeof x)-1 }
|
520
|
-
_aprotocol( "http://" ),
|
521
418
|
_aprotocol( "https://" ),
|
522
|
-
_aprotocol( "
|
419
|
+
_aprotocol( "http://" ),
|
523
420
|
_aprotocol( "news://" ),
|
421
|
+
_aprotocol( "ftp://" ),
|
524
422
|
#undef _aprotocol
|
525
423
|
};
|
526
424
|
#define NRPROTOCOLS (sizeof protocol / sizeof protocol[0])
|
527
425
|
|
528
426
|
|
529
427
|
static int
|
530
|
-
isautoprefix(char *text)
|
428
|
+
isautoprefix(char *text, int size)
|
531
429
|
{
|
532
430
|
int i;
|
431
|
+
struct _protocol *p;
|
533
432
|
|
534
|
-
for (i=0; i < NRPROTOCOLS; i++)
|
535
|
-
if ( strncasecmp(text,
|
433
|
+
for (i=0, p=protocol; i < NRPROTOCOLS; i++, p++)
|
434
|
+
if ( (size >= p->nlen) && strncasecmp(text, p->name, p->nlen) == 0 )
|
536
435
|
return 1;
|
537
436
|
return 0;
|
538
437
|
}
|
@@ -584,8 +483,7 @@ pseudo(Cstring t)
|
|
584
483
|
int i;
|
585
484
|
linkytype *r;
|
586
485
|
|
587
|
-
for ( i=0; i < NR(specials); i++ ) {
|
588
|
-
r = &specials[i];
|
486
|
+
for ( i=0, r=specials; i < NR(specials); i++,r++ ) {
|
589
487
|
if ( (S(t) > r->szpat) && (strncasecmp(T(t), r->pat, r->szpat) == 0) )
|
590
488
|
return r;
|
591
489
|
}
|
@@ -593,6 +491,36 @@ pseudo(Cstring t)
|
|
593
491
|
}
|
594
492
|
|
595
493
|
|
494
|
+
/* print out the start of an `img' or `a' tag, applying callbacks as needed.
|
495
|
+
*/
|
496
|
+
static void
|
497
|
+
printlinkyref(MMIOT *f, linkytype *tag, char *link, int size)
|
498
|
+
{
|
499
|
+
char *edit;
|
500
|
+
|
501
|
+
Qstring(tag->link_pfx, f);
|
502
|
+
|
503
|
+
if ( tag->kind & IS_URL ) {
|
504
|
+
if ( f->cb->e_url && (edit = (*f->cb->e_url)(link, size, f->cb->e_data)) ) {
|
505
|
+
puturl(edit, strlen(edit), f, 0);
|
506
|
+
if ( f->cb->e_free ) (*f->cb->e_free)(edit, f->cb->e_data);
|
507
|
+
}
|
508
|
+
else
|
509
|
+
puturl(link + tag->szpat, size - tag->szpat, f, 0);
|
510
|
+
}
|
511
|
+
else
|
512
|
+
___mkd_reparse(link + tag->szpat, size - tag->szpat, INSIDE_TAG, f);
|
513
|
+
|
514
|
+
Qstring(tag->link_sfx, f);
|
515
|
+
|
516
|
+
if ( f->cb->e_flags && (edit = (*f->cb->e_flags)(link, size, f->cb->e_data)) ) {
|
517
|
+
Qchar(' ', f);
|
518
|
+
Qstring(edit, f);
|
519
|
+
if ( f->cb->e_free ) (*f->cb->e_free)(edit, f->cb->e_data);
|
520
|
+
}
|
521
|
+
} /* printlinkyref */
|
522
|
+
|
523
|
+
|
596
524
|
/* print out a linky (or fail if it's Not Allowed)
|
597
525
|
*/
|
598
526
|
static int
|
@@ -608,11 +536,11 @@ linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref)
|
|
608
536
|
}
|
609
537
|
else if ( (f->flags & SAFELINK) && T(ref->link)
|
610
538
|
&& (T(ref->link)[0] != '/')
|
611
|
-
&& !isautoprefix(T(ref->link)) )
|
539
|
+
&& !isautoprefix(T(ref->link), S(ref->link)) )
|
612
540
|
/* if SAFELINK, only accept links that are local or
|
613
541
|
* a well-known protocol
|
614
542
|
*/
|
615
|
-
|
543
|
+
return 0;
|
616
544
|
else
|
617
545
|
tag = &linkt;
|
618
546
|
|
@@ -620,21 +548,11 @@ linkyformat(MMIOT *f, Cstring text, int image, Footnote *ref)
|
|
620
548
|
return 0;
|
621
549
|
|
622
550
|
if ( tag->link_pfx ) {
|
623
|
-
|
624
|
-
|
625
|
-
if ( tag->kind & IS_URL ) {
|
626
|
-
if ( f->base && T(ref->link) && (T(ref->link)[tag->szpat] == '/') )
|
627
|
-
puturl(f->base, strlen(f->base), f, 0);
|
628
|
-
puturl(T(ref->link) + tag->szpat, S(ref->link) - tag->szpat, f, 0);
|
629
|
-
}
|
630
|
-
else
|
631
|
-
___mkd_reparse(T(ref->link) + tag->szpat, S(ref->link) - tag->szpat, INSIDE_TAG, f);
|
632
|
-
|
633
|
-
Qstring(tag->link_sfx, f);
|
551
|
+
printlinkyref(f, tag, T(ref->link), S(ref->link));
|
634
552
|
|
635
|
-
if ( tag->WxH) {
|
636
|
-
if ( ref->height) Qprintf(f," height=\"%d\"", ref->height);
|
637
|
-
if ( ref->width) Qprintf(f, " width=\"%d\"", ref->width);
|
553
|
+
if ( tag->WxH ) {
|
554
|
+
if ( ref->height ) Qprintf(f," height=\"%d\"", ref->height);
|
555
|
+
if ( ref->width ) Qprintf(f, " width=\"%d\"", ref->width);
|
638
556
|
}
|
639
557
|
|
640
558
|
if ( S(ref->title) ) {
|
@@ -742,6 +660,89 @@ mangle(char *s, int len, MMIOT *f)
|
|
742
660
|
}
|
743
661
|
|
744
662
|
|
663
|
+
/* nrticks() -- count up a row of tick marks
|
664
|
+
*/
|
665
|
+
static int
|
666
|
+
nrticks(int offset, MMIOT *f)
|
667
|
+
{
|
668
|
+
int tick = 0;
|
669
|
+
|
670
|
+
while ( peek(f, offset+tick) == '`' ) tick++;
|
671
|
+
|
672
|
+
return tick;
|
673
|
+
} /* nrticks */
|
674
|
+
|
675
|
+
|
676
|
+
/* matchticks() -- match a certain # of ticks, and if that fails
|
677
|
+
* match the largest subset of those ticks.
|
678
|
+
*
|
679
|
+
* if a subset was matched, modify the passed in
|
680
|
+
* # of ticks so that the caller (text()) can
|
681
|
+
* appropriately process the horrible thing.
|
682
|
+
*/
|
683
|
+
static int
|
684
|
+
matchticks(MMIOT *f, int *ticks)
|
685
|
+
{
|
686
|
+
int size, tick, c;
|
687
|
+
int subsize=0, subtick=0;
|
688
|
+
|
689
|
+
for (size = *ticks; (c=peek(f,size)) != EOF; ) {
|
690
|
+
if ( c == '`' )
|
691
|
+
if ( (tick=nrticks(size,f)) == *ticks )
|
692
|
+
return size;
|
693
|
+
else {
|
694
|
+
if ( tick > subtick ) {
|
695
|
+
subsize = size;
|
696
|
+
subtick = tick;
|
697
|
+
}
|
698
|
+
size += tick;
|
699
|
+
}
|
700
|
+
else
|
701
|
+
size++;
|
702
|
+
}
|
703
|
+
if ( subsize ) {
|
704
|
+
*ticks = subtick;
|
705
|
+
return subsize;
|
706
|
+
}
|
707
|
+
return 0;
|
708
|
+
|
709
|
+
} /* matchticks */
|
710
|
+
|
711
|
+
|
712
|
+
/* code() -- write a string out as code. The only characters that have
|
713
|
+
* special meaning in a code block are * `<' and `&' , which
|
714
|
+
* are /always/ expanded to < and &
|
715
|
+
*/
|
716
|
+
static void
|
717
|
+
code(MMIOT *f, char *s, int length)
|
718
|
+
{
|
719
|
+
int i,c;
|
720
|
+
|
721
|
+
for ( i=0; i < length; i++ )
|
722
|
+
if ( (c = s[i]) == 003) /* ^C: expand back to 2 spaces */
|
723
|
+
Qstring(" ", f);
|
724
|
+
else
|
725
|
+
cputc(c, f);
|
726
|
+
} /* code */
|
727
|
+
|
728
|
+
|
729
|
+
/* codespan() -- write out a chunk of text as code, trimming one
|
730
|
+
* space off the front and/or back as appropriate.
|
731
|
+
*/
|
732
|
+
static void
|
733
|
+
codespan(MMIOT *f, int size)
|
734
|
+
{
|
735
|
+
int i=0, c;
|
736
|
+
|
737
|
+
if ( size > 1 && peek(f, size-1) == ' ' ) --size;
|
738
|
+
if ( peek(f,i) == ' ' ) ++i, --size;
|
739
|
+
|
740
|
+
Qstring("<code>", f);
|
741
|
+
code(f, cursor(f)+(i-1), size);
|
742
|
+
Qstring("</code>", f);
|
743
|
+
} /* codespan */
|
744
|
+
|
745
|
+
|
745
746
|
/* before letting a tag through, validate against
|
746
747
|
* DENY_A and DENY_IMG
|
747
748
|
*/
|
@@ -826,10 +827,9 @@ process_possible_link(MMIOT *f, int size)
|
|
826
827
|
Qstring("</a>", f);
|
827
828
|
return 1;
|
828
829
|
}
|
829
|
-
else if ( isautoprefix(text) ) {
|
830
|
-
|
831
|
-
|
832
|
-
Qstring("\">", f);
|
830
|
+
else if ( isautoprefix(text, size) ) {
|
831
|
+
printlinkyref(f, &linkt, text, size);
|
832
|
+
Qchar('>', f);
|
833
833
|
puturl(text,size,f, 1);
|
834
834
|
Qstring("</a>", f);
|
835
835
|
return 1;
|
@@ -879,7 +879,10 @@ maybe_tag_or_link(MMIOT *f)
|
|
879
879
|
else
|
880
880
|
size++;
|
881
881
|
|
882
|
-
|
882
|
+
if ( forbidden_tag(f) )
|
883
|
+
return 0;
|
884
|
+
|
885
|
+
Qchar('<', f);
|
883
886
|
while ( ((c = peek(f, 1)) != EOF) && (c != '>') )
|
884
887
|
Qchar(pull(f), f);
|
885
888
|
return 1;
|
@@ -1065,7 +1068,7 @@ text(MMIOT *f)
|
|
1065
1068
|
int smartyflags = 0;
|
1066
1069
|
|
1067
1070
|
while (1) {
|
1068
|
-
if ( (f->flags & AUTOLINK) && isalpha(peek(f,1)) )
|
1071
|
+
if ( (f->flags & AUTOLINK) && isalpha(peek(f,1)) && !tag_text(f) )
|
1069
1072
|
maybe_autolink(f);
|
1070
1073
|
|
1071
1074
|
c = pull(f);
|
@@ -1078,7 +1081,7 @@ text(MMIOT *f)
|
|
1078
1081
|
switch (c) {
|
1079
1082
|
case 0: break;
|
1080
1083
|
|
1081
|
-
case 3: Qstring("<br/>", f);
|
1084
|
+
case 3: Qstring(tag_text(f) ? " " : "<br/>", f);
|
1082
1085
|
break;
|
1083
1086
|
|
1084
1087
|
case '>': if ( tag_text(f) )
|
@@ -1131,16 +1134,13 @@ text(MMIOT *f)
|
|
1131
1134
|
}
|
1132
1135
|
#endif
|
1133
1136
|
case '*':
|
1134
|
-
#if RELAXED_EMPHASIS
|
1135
1137
|
/* Underscores & stars don't count if they're out in the middle
|
1136
1138
|
* of whitespace */
|
1137
|
-
if (
|
1138
|
-
&& isthisspace(f,1) ) {
|
1139
|
+
if ( isthisspace(f,-1) && isthisspace(f,1) ) {
|
1139
1140
|
Qchar(c, f);
|
1140
1141
|
break;
|
1141
1142
|
}
|
1142
1143
|
/* else fall into the regular old emphasis case */
|
1143
|
-
#endif
|
1144
1144
|
if ( tag_text(f) )
|
1145
1145
|
Qchar(c, f);
|
1146
1146
|
else {
|
@@ -1150,17 +1150,20 @@ text(MMIOT *f)
|
|
1150
1150
|
}
|
1151
1151
|
break;
|
1152
1152
|
|
1153
|
-
case '`': if ( tag_text(f)
|
1153
|
+
case '`': if ( tag_text(f) )
|
1154
1154
|
Qchar(c, f);
|
1155
1155
|
else {
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1156
|
+
int size, tick = nrticks(0, f);
|
1157
|
+
|
1158
|
+
if ( size = matchticks(f, &tick) ) {
|
1159
|
+
shift(f, tick);
|
1160
|
+
codespan(f, size-tick);
|
1161
|
+
shift(f, size-1);
|
1162
|
+
}
|
1163
|
+
else {
|
1164
|
+
Qchar(c, f);
|
1165
|
+
Qcopy(tick-1, f);
|
1160
1166
|
}
|
1161
|
-
else
|
1162
|
-
code(1, f);
|
1163
|
-
Qstring("</code>", f);
|
1164
1167
|
}
|
1165
1168
|
break;
|
1166
1169
|
|
@@ -1169,11 +1172,10 @@ text(MMIOT *f)
|
|
1169
1172
|
break;
|
1170
1173
|
case '<': Qstring("<", f);
|
1171
1174
|
break;
|
1172
|
-
case '\\':
|
1173
1175
|
case '>': case '#': case '.': case '-':
|
1174
1176
|
case '+': case '{': case '}': case ']':
|
1175
|
-
case '(': case ')': case '"': case '\'':
|
1176
1177
|
case '!': case '[': case '*': case '_':
|
1178
|
+
case '\\':case '(': case ')':
|
1177
1179
|
case '`': Qchar(c, f);
|
1178
1180
|
break;
|
1179
1181
|
default:
|
@@ -1207,74 +1209,6 @@ text(MMIOT *f)
|
|
1207
1209
|
} /* text */
|
1208
1210
|
|
1209
1211
|
|
1210
|
-
static int
|
1211
|
-
iscodeblock(MMIOT *f)
|
1212
|
-
{
|
1213
|
-
int i=1, single = 1, c;
|
1214
|
-
|
1215
|
-
if ( peek(f,i) == '`' ) {
|
1216
|
-
single=0;
|
1217
|
-
i++;
|
1218
|
-
}
|
1219
|
-
while ( (c=peek(f,i)) != EOF ) {
|
1220
|
-
if ( (c == '`') && (single || peek(f,i+1) == '`') )
|
1221
|
-
return 1;
|
1222
|
-
else if ( c == '\\' )
|
1223
|
-
i++;
|
1224
|
-
i++;
|
1225
|
-
}
|
1226
|
-
return 0;
|
1227
|
-
|
1228
|
-
}
|
1229
|
-
|
1230
|
-
static int
|
1231
|
-
endofcode(int escape, int offset, MMIOT *f)
|
1232
|
-
{
|
1233
|
-
switch (escape) {
|
1234
|
-
case 2: if ( peek(f, offset+1) == '`' ) {
|
1235
|
-
shift(f,1);
|
1236
|
-
case 1: shift(f,offset);
|
1237
|
-
return 1;
|
1238
|
-
}
|
1239
|
-
default:return 0;
|
1240
|
-
}
|
1241
|
-
}
|
1242
|
-
|
1243
|
-
|
1244
|
-
/* the only characters that have special meaning in a code block are
|
1245
|
-
* `<' and `&' , which are /always/ expanded to < and &
|
1246
|
-
*/
|
1247
|
-
static void
|
1248
|
-
code(int escape, MMIOT *f)
|
1249
|
-
{
|
1250
|
-
int c;
|
1251
|
-
|
1252
|
-
if ( escape && (peek(f,1) == ' ') )
|
1253
|
-
shift(f,1);
|
1254
|
-
|
1255
|
-
while ( (c = pull(f)) != EOF ) {
|
1256
|
-
switch (c) {
|
1257
|
-
case ' ': if ( peek(f,1) == '`' && endofcode(escape, 1, f) )
|
1258
|
-
return;
|
1259
|
-
Qchar(c, f);
|
1260
|
-
break;
|
1261
|
-
|
1262
|
-
case '`': if ( endofcode(escape, 0, f) )
|
1263
|
-
return;
|
1264
|
-
Qchar(c, f);
|
1265
|
-
break;
|
1266
|
-
|
1267
|
-
case '\\': cputc(c, f);
|
1268
|
-
if ( peek(f,1) == '>' || (c = pull(f)) == EOF )
|
1269
|
-
break;
|
1270
|
-
|
1271
|
-
default: cputc(c, f);
|
1272
|
-
break;
|
1273
|
-
}
|
1274
|
-
}
|
1275
|
-
} /* code */
|
1276
|
-
|
1277
|
-
|
1278
1212
|
/* print a header block
|
1279
1213
|
*/
|
1280
1214
|
static void
|
@@ -1333,6 +1267,7 @@ splat(Line *p, char *block, Istring align, int force, MMIOT *f)
|
|
1333
1267
|
return colno;
|
1334
1268
|
}
|
1335
1269
|
|
1270
|
+
|
1336
1271
|
static int
|
1337
1272
|
printtable(Paragraph *pp, MMIOT *f)
|
1338
1273
|
{
|
@@ -1402,8 +1337,9 @@ printblock(Paragraph *pp, MMIOT *f)
|
|
1402
1337
|
|
1403
1338
|
while (t) {
|
1404
1339
|
if ( S(t->text) ) {
|
1405
|
-
if (
|
1406
|
-
|
1340
|
+
if ( t->next && S(t->text) > 2
|
1341
|
+
&& T(t->text)[S(t->text)-2] == ' '
|
1342
|
+
&& T(t->text)[S(t->text)-1] == ' ' ) {
|
1407
1343
|
push(T(t->text), S(t->text)-2, f);
|
1408
1344
|
push("\003\n", 2, f);
|
1409
1345
|
}
|
@@ -1428,19 +1364,18 @@ printcode(Line *t, MMIOT *f)
|
|
1428
1364
|
{
|
1429
1365
|
int blanks;
|
1430
1366
|
|
1431
|
-
|
1367
|
+
Qstring("<pre><code>", f);
|
1368
|
+
for ( blanks = 0; t ; t = t->next ) {
|
1432
1369
|
if ( S(t->text) > t->dle ) {
|
1433
1370
|
while ( blanks ) {
|
1434
|
-
|
1371
|
+
Qchar('\n', f);
|
1435
1372
|
--blanks;
|
1436
1373
|
}
|
1437
|
-
|
1438
|
-
|
1374
|
+
code(f, T(t->text), S(t->text));
|
1375
|
+
Qchar('\n', f);
|
1439
1376
|
}
|
1440
1377
|
else blanks++;
|
1441
|
-
|
1442
|
-
Qstring("<pre><code>", f);
|
1443
|
-
code(0, f);
|
1378
|
+
}
|
1444
1379
|
Qstring("</code></pre>", f);
|
1445
1380
|
}
|
1446
1381
|
|
data/ext/markdown.c
CHANGED
@@ -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] == ']'
|
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,11 +315,14 @@ isfootnote(Line *t)
|
|
315
315
|
static int
|
316
316
|
isquote(Line *t)
|
317
317
|
{
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
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;
|
323
326
|
}
|
324
327
|
|
325
328
|
|
@@ -386,13 +389,14 @@ ishdr(Line *t, int *htyp)
|
|
386
389
|
|
387
390
|
if ( t->next ) {
|
388
391
|
char *q = T(t->next->text);
|
392
|
+
int last = S(t->next->text);
|
389
393
|
|
390
394
|
if ( (*q == '=') || (*q == '-') ) {
|
391
|
-
/*
|
392
|
-
|
393
|
-
|
395
|
+
/* ignore trailing whitespace */
|
396
|
+
while ( (last > 1) && isspace(q[last-1]) )
|
397
|
+
--last;
|
394
398
|
|
395
|
-
for (i=1; i
|
399
|
+
for (i=1; i < last; i++)
|
396
400
|
if ( q[0] != q[i] )
|
397
401
|
return 0;
|
398
402
|
*htyp = SETEXT;
|
@@ -483,7 +487,8 @@ headerblock(Paragraph *pp, int htyp)
|
|
483
487
|
* the leading and trailing `#`'s
|
484
488
|
*/
|
485
489
|
|
486
|
-
for (i=0; (T(p->text)[i] == T(p->text)[0]) && (i < S(p->text)-1)
|
490
|
+
for (i=0; (T(p->text)[i] == T(p->text)[0]) && (i < S(p->text)-1)
|
491
|
+
&& (i < 6); i++)
|
487
492
|
;
|
488
493
|
|
489
494
|
pp->hnumber = i;
|
@@ -637,9 +642,16 @@ quoteblock(Paragraph *p)
|
|
637
642
|
|
638
643
|
for ( t = p->text; t ; t = q ) {
|
639
644
|
if ( isquote(t) ) {
|
640
|
-
|
641
|
-
|
642
|
-
|
645
|
+
/* clip leading spaces */
|
646
|
+
for (qp = 0; T(t->text)[qp] != '>'; qp ++)
|
647
|
+
/* assert: the first nonblank character on this line
|
648
|
+
* will be a >
|
649
|
+
*/;
|
650
|
+
/* clip '>' */
|
651
|
+
qp++;
|
652
|
+
/* clip next space, if any */
|
653
|
+
if ( T(t->text)[qp] == ' ' )
|
654
|
+
qp++;
|
643
655
|
CLIP(t->text, 0, qp);
|
644
656
|
t->dle = mkd_firstnonblank(t);
|
645
657
|
}
|
@@ -719,8 +731,9 @@ listitem(Paragraph *p, int indent)
|
|
719
731
|
}
|
720
732
|
|
721
733
|
/* after a blank line, the next block needs to start with a line
|
722
|
-
* that's indented 4
|
723
|
-
*
|
734
|
+
* that's indented 4(? -- reference implementation allows a 1
|
735
|
+
* character indent, but that has unfortunate side effects here)
|
736
|
+
* spaces, but after that the line doesn't need any indentation
|
724
737
|
*/
|
725
738
|
if ( q != t->next ) {
|
726
739
|
if (q->dle < indent) {
|
@@ -728,7 +741,8 @@ listitem(Paragraph *p, int indent)
|
|
728
741
|
t->next = 0;
|
729
742
|
return q;
|
730
743
|
}
|
731
|
-
indent
|
744
|
+
/* indent as far as the initial line was indented. */
|
745
|
+
indent = clip;
|
732
746
|
}
|
733
747
|
|
734
748
|
if ( (q->dle < indent) && (ishr(q) || islist(q,&z)) && !ishdr(q,&z) ) {
|
@@ -1070,8 +1084,8 @@ mkd_compile(Document *doc, int flags)
|
|
1070
1084
|
|
1071
1085
|
doc->compiled = 1;
|
1072
1086
|
memset(doc->ctx, 0, sizeof(MMIOT) );
|
1073
|
-
doc->ctx->
|
1074
|
-
doc->ctx->
|
1087
|
+
doc->ctx->cb = &(doc->cb);
|
1088
|
+
doc->ctx->flags = flags & USER_FLAGS;
|
1075
1089
|
CREATE(doc->ctx->in);
|
1076
1090
|
doc->ctx->footnotes = malloc(sizeof doc->ctx->footnotes[0]);
|
1077
1091
|
CREATE(*doc->ctx->footnotes);
|
data/ext/markdown.h
CHANGED
@@ -56,6 +56,17 @@ typedef struct block {
|
|
56
56
|
typedef STRING(block) Qblock;
|
57
57
|
|
58
58
|
|
59
|
+
typedef char* (*mkd_callback_t)(const char*, const int, void*);
|
60
|
+
typedef void (*mkd_free_t)(char*, void*);
|
61
|
+
|
62
|
+
typedef struct callback_data {
|
63
|
+
void *e_data; /* private data for callbacks */
|
64
|
+
mkd_callback_t e_url; /* url edit callback */
|
65
|
+
mkd_callback_t e_flags; /* extra href flags callback */
|
66
|
+
mkd_free_t e_free; /* edit/flags callback memory deallocator */
|
67
|
+
} Callback_data;
|
68
|
+
|
69
|
+
|
59
70
|
/* a magic markdown io thing holds all the data structures needed to
|
60
71
|
* do the backend processing of a markdown document
|
61
72
|
*/
|
@@ -81,7 +92,7 @@ typedef struct mmiot {
|
|
81
92
|
#define SAFELINK 0x8000
|
82
93
|
#define USER_FLAGS 0xFCFF
|
83
94
|
#define EMBEDDED DENY_A|DENY_IMG|NO_PSEUDO_PROTO|CDATA_OUTPUT
|
84
|
-
|
95
|
+
Callback_data *cb;
|
85
96
|
} MMIOT;
|
86
97
|
|
87
98
|
|
@@ -100,7 +111,7 @@ typedef struct document {
|
|
100
111
|
int html; /* set after (internal) htmlify() */
|
101
112
|
int tabstop; /* for properly expanding tabs (ick) */
|
102
113
|
MMIOT *ctx; /* backend buffers, flags, and structures */
|
103
|
-
|
114
|
+
Callback_data cb; /* callback functions & private data */
|
104
115
|
} Document;
|
105
116
|
|
106
117
|
|
data/ext/mkdio.c
CHANGED
@@ -217,14 +217,6 @@ markdown(Document *document, FILE *out, int flags)
|
|
217
217
|
}
|
218
218
|
|
219
219
|
|
220
|
-
void
|
221
|
-
mkd_basename(Document *document, char *base)
|
222
|
-
{
|
223
|
-
if ( document )
|
224
|
-
document->base = base;
|
225
|
-
}
|
226
|
-
|
227
|
-
|
228
220
|
/* write out a Cstring, mangled into a form suitable for `<a href=` or `<a id=`
|
229
221
|
*/
|
230
222
|
void
|
@@ -301,3 +293,43 @@ mkd_generateline(char *bfr, int size, FILE *output, int flags)
|
|
301
293
|
___mkd_freemmiot(&f, 0);
|
302
294
|
return 0;
|
303
295
|
}
|
296
|
+
|
297
|
+
|
298
|
+
/* set the url display callback
|
299
|
+
*/
|
300
|
+
void
|
301
|
+
mkd_e_url(Document *f, mkd_callback_t edit)
|
302
|
+
{
|
303
|
+
if ( f )
|
304
|
+
f->cb.e_url = edit;
|
305
|
+
}
|
306
|
+
|
307
|
+
|
308
|
+
/* set the url options callback
|
309
|
+
*/
|
310
|
+
void
|
311
|
+
mkd_e_flags(Document *f, mkd_callback_t edit)
|
312
|
+
{
|
313
|
+
if ( f )
|
314
|
+
f->cb.e_flags = edit;
|
315
|
+
}
|
316
|
+
|
317
|
+
|
318
|
+
/* set the url display/options deallocator
|
319
|
+
*/
|
320
|
+
void
|
321
|
+
mkd_e_free(Document *f, mkd_free_t dealloc)
|
322
|
+
{
|
323
|
+
if ( f )
|
324
|
+
f->cb.e_free = dealloc;
|
325
|
+
}
|
326
|
+
|
327
|
+
|
328
|
+
/* set the url display/options context data field
|
329
|
+
*/
|
330
|
+
void
|
331
|
+
mkd_e_data(Document *f, void *data)
|
332
|
+
{
|
333
|
+
if ( f )
|
334
|
+
f->cb.e_data = data;
|
335
|
+
}
|
data/ext/mkdio.h
CHANGED
@@ -48,6 +48,16 @@ int mkd_generatecss(MMIOT*,FILE*);
|
|
48
48
|
int mkd_generateline(char *, int, FILE*, int);
|
49
49
|
#define mkd_text mkd_generateline
|
50
50
|
|
51
|
+
/* url generator callbacks
|
52
|
+
*/
|
53
|
+
typedef char * (*mkd_callback_t)(const char*, const int, void*);
|
54
|
+
typedef void (*mkd_free_t)(char*, void*);
|
55
|
+
|
56
|
+
void mkd_e_url(void *, mkd_callback_t);
|
57
|
+
void mkd_e_flags(void *, mkd_callback_t);
|
58
|
+
void mkd_e_free(void *, mkd_free_t );
|
59
|
+
void mkd_e_data(void *, void *);
|
60
|
+
|
51
61
|
/* version#.
|
52
62
|
*/
|
53
63
|
extern char markdown_version[];
|
data/lib/rdiscount.rb
CHANGED
data/rdiscount.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'rdiscount'
|
3
|
-
s.version = '1.
|
3
|
+
s.version = '1.6.3'
|
4
4
|
s.summary = "Fast Implementation of Gruber's Markdown in C"
|
5
5
|
s.date = '2010-03-08'
|
6
6
|
s.email = 'r@tomayko.com'
|
@@ -15,11 +15,13 @@ Gem::Specification.new do |s|
|
|
15
15
|
bin/rdiscount
|
16
16
|
ext/Csio.c
|
17
17
|
ext/amalloc.h
|
18
|
+
ext/basename.c
|
18
19
|
ext/config.h
|
19
20
|
ext/css.c
|
20
21
|
ext/cstring.h
|
21
22
|
ext/docheader.c
|
22
23
|
ext/dumptree.c
|
24
|
+
ext/emmatch.c
|
23
25
|
ext/extconf.rb
|
24
26
|
ext/generate.c
|
25
27
|
ext/markdown.c
|
data/test/markdown_test.rb
CHANGED
@@ -129,7 +129,7 @@ class MarkdownTest < Test::Unit::TestCase
|
|
129
129
|
"=================== \n\n" +
|
130
130
|
"By Candice Yellowflower \n"
|
131
131
|
markdown = Markdown.new(text)
|
132
|
-
assert_equal "<h1>The Ant-Sugar Tales </h1>\n\n<p>By Candice Yellowflower
|
132
|
+
assert_equal "<h1>The Ant-Sugar Tales </h1>\n\n<p>By Candice Yellowflower</p>\n",
|
133
133
|
markdown.to_html
|
134
134
|
end
|
135
135
|
|
metadata
CHANGED
@@ -4,10 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 1
|
7
|
-
-
|
8
|
-
-
|
9
|
-
|
10
|
-
version: 1.5.8.1
|
7
|
+
- 6
|
8
|
+
- 3
|
9
|
+
version: 1.6.3
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Ryan Tomayko
|
@@ -36,11 +35,13 @@ files:
|
|
36
35
|
- bin/rdiscount
|
37
36
|
- ext/Csio.c
|
38
37
|
- ext/amalloc.h
|
38
|
+
- ext/basename.c
|
39
39
|
- ext/config.h
|
40
40
|
- ext/css.c
|
41
41
|
- ext/cstring.h
|
42
42
|
- ext/docheader.c
|
43
43
|
- ext/dumptree.c
|
44
|
+
- ext/emmatch.c
|
44
45
|
- ext/extconf.rb
|
45
46
|
- ext/generate.c
|
46
47
|
- ext/markdown.c
|