rdiscount 1.3.5 → 1.5.5
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/README.markdown +20 -10
- data/Rakefile +12 -11
- data/ext/Csio.c +14 -2
- data/ext/css.c +76 -0
- data/ext/cstring.h +7 -5
- data/ext/dumptree.c +5 -1
- data/ext/generate.c +473 -268
- data/ext/markdown.c +209 -96
- data/ext/markdown.h +16 -5
- data/ext/mkdio.c +68 -6
- data/ext/mkdio.h +20 -7
- data/ext/resource.c +13 -27
- data/ext/toc.c +24 -20
- data/ext/xml.c +82 -0
- data/lib/rdiscount.rb +2 -2
- data/rdiscount.gemspec +4 -2
- data/test/markdown_test.rb +17 -0
- metadata +5 -3
data/ext/markdown.h
CHANGED
@@ -11,6 +11,7 @@ typedef struct footnote {
|
|
11
11
|
Cstring link; /* what this footnote points to */
|
12
12
|
Cstring title; /* what it's called (TITLE= attribute) */
|
13
13
|
int height, width; /* dimensions (for image link) */
|
14
|
+
int dealloc; /* deallocation needed? */
|
14
15
|
} Footnote;
|
15
16
|
|
16
17
|
/* each input line is read into a Line, which contains the line,
|
@@ -36,7 +37,7 @@ typedef struct paragraph {
|
|
36
37
|
char *ident; /* %id% tag for QUOTE */
|
37
38
|
enum { WHITESPACE=0, CODE, QUOTE, MARKUP,
|
38
39
|
HTML, STYLE, DL, UL, OL, AL, LISTITEM,
|
39
|
-
HDR, HR } typ;
|
40
|
+
HDR, HR, TABLE, SOURCE } typ;
|
40
41
|
enum { IMPLICIT=0, PARA, CENTER} align;
|
41
42
|
int hnumber; /* <Hn> for typ == HDR */
|
42
43
|
} Paragraph;
|
@@ -73,9 +74,12 @@ typedef struct mmiot {
|
|
73
74
|
#define INSIDE_TAG 0x0020
|
74
75
|
#define NO_PSEUDO_PROTO 0x0040
|
75
76
|
#define CDATA_OUTPUT 0x0080
|
77
|
+
#define NOTABLES 0x0400
|
76
78
|
#define TOC 0x1000
|
77
79
|
#define MKD_1_COMPAT 0x2000
|
78
|
-
#define
|
80
|
+
#define AUTOLINK 0x4000
|
81
|
+
#define SAFELINK 0x8000
|
82
|
+
#define USER_FLAGS 0xFCFF
|
79
83
|
#define EMBEDDED DENY_A|DENY_IMG|NO_PSEUDO_PROTO|CDATA_OUTPUT
|
80
84
|
char *base;
|
81
85
|
} MMIOT;
|
@@ -104,9 +108,15 @@ extern int mkd_firstnonblank(Line *);
|
|
104
108
|
extern int mkd_compile(Document *, int);
|
105
109
|
extern int mkd_document(Document *, char **);
|
106
110
|
extern int mkd_generatehtml(Document *, FILE *);
|
107
|
-
extern int
|
111
|
+
extern int mkd_css(Document *, char **);
|
112
|
+
extern int mkd_generatecss(Document *, FILE *);
|
113
|
+
#define mkd_style mkd_generatecss
|
114
|
+
extern int mkd_xml(char *, int , char **);
|
115
|
+
extern int mkd_generatexml(char *, int, FILE *);
|
108
116
|
extern void mkd_cleanup(Document *);
|
109
|
-
extern int
|
117
|
+
extern int mkd_line(char *, int, char **, int);
|
118
|
+
extern int mkd_generateline(char *, int, FILE*, int);
|
119
|
+
#define mkd_text mkd_generateline
|
110
120
|
extern void mkd_basename(Document*, char *);
|
111
121
|
extern void mkd_string_to_anchor(char*,int, void(*)(int,void*), void*);
|
112
122
|
|
@@ -123,6 +133,7 @@ extern Document *mkd_string(char*,int, int);
|
|
123
133
|
extern void ___mkd_freeLine(Line *);
|
124
134
|
extern void ___mkd_freeLines(Line *);
|
125
135
|
extern void ___mkd_freeParagraph(Paragraph *);
|
136
|
+
extern void ___mkd_freefootnote(Footnote *);
|
126
137
|
extern void ___mkd_freefootnotes(MMIOT *);
|
127
138
|
extern void ___mkd_initmmiot(MMIOT *, void *);
|
128
139
|
extern void ___mkd_freemmiot(MMIOT *, void *);
|
@@ -130,6 +141,6 @@ extern void ___mkd_freeLineRange(Line *, Line *);
|
|
130
141
|
extern void ___mkd_xml(char *, int, FILE *);
|
131
142
|
extern void ___mkd_reparse(char *, int, int, MMIOT*);
|
132
143
|
extern void ___mkd_emblock(MMIOT*);
|
133
|
-
extern void ___mkd_tidy(
|
144
|
+
extern void ___mkd_tidy(Cstring *);
|
134
145
|
|
135
146
|
#endif/*_MARKDOWN_D*/
|
data/ext/mkdio.c
CHANGED
@@ -113,7 +113,7 @@ populate(getc_func getc, void* ctx, int flags)
|
|
113
113
|
queue(a, &line);
|
114
114
|
S(line) = 0;
|
115
115
|
}
|
116
|
-
else
|
116
|
+
else if ( isprint(c) || isspace(c) || (c & 0x80) )
|
117
117
|
EXPAND(line) = c;
|
118
118
|
}
|
119
119
|
|
@@ -193,7 +193,7 @@ mkd_generatehtml(Document *p, FILE *output)
|
|
193
193
|
|
194
194
|
if ( (szdoc = mkd_document(p, &doc)) != EOF ) {
|
195
195
|
if ( p->ctx->flags & CDATA_OUTPUT )
|
196
|
-
|
196
|
+
mkd_generatexml(doc, szdoc, output);
|
197
197
|
else
|
198
198
|
fwrite(doc, szdoc, 1, output);
|
199
199
|
putc('\n', output);
|
@@ -230,12 +230,74 @@ mkd_basename(Document *document, char *base)
|
|
230
230
|
void
|
231
231
|
mkd_string_to_anchor(char *s, int len, void(*outchar)(int,void*), void *out)
|
232
232
|
{
|
233
|
-
|
234
|
-
|
233
|
+
unsigned char c;
|
234
|
+
|
235
|
+
for ( ; len-- > 0; ) {
|
236
|
+
c = *s++;
|
237
|
+
if ( c == ' ' || c == '&' || c == '<' || c == '"' )
|
235
238
|
(*outchar)('+', out);
|
236
|
-
else if ( isalnum(
|
237
|
-
(*outchar)(
|
239
|
+
else if ( isalnum(c) || ispunct(c) || (c & 0x80) )
|
240
|
+
(*outchar)(c, out);
|
238
241
|
else
|
239
242
|
(*outchar)('~',out);
|
240
243
|
}
|
241
244
|
}
|
245
|
+
|
246
|
+
|
247
|
+
/* ___mkd_reparse() a line
|
248
|
+
*/
|
249
|
+
static void
|
250
|
+
mkd_parse_line(char *bfr, int size, MMIOT *f, int flags)
|
251
|
+
{
|
252
|
+
___mkd_initmmiot(f, 0);
|
253
|
+
f->flags = flags & USER_FLAGS;
|
254
|
+
___mkd_reparse(bfr, size, 0, f);
|
255
|
+
___mkd_emblock(f);
|
256
|
+
}
|
257
|
+
|
258
|
+
|
259
|
+
/* ___mkd_reparse() a line, returning it in malloc()ed memory
|
260
|
+
*/
|
261
|
+
int
|
262
|
+
mkd_line(char *bfr, int size, char **res, int flags)
|
263
|
+
{
|
264
|
+
MMIOT f;
|
265
|
+
int len;
|
266
|
+
|
267
|
+
mkd_parse_line(bfr, size, &f, flags);
|
268
|
+
|
269
|
+
if ( len = S(f.out) ) {
|
270
|
+
/* kludge alert; we know that T(f.out) is malloced memory,
|
271
|
+
* so we can just steal it away. This is awful -- there
|
272
|
+
* should be an opaque method that transparently moves
|
273
|
+
* the pointer out of the embedded Cstring.
|
274
|
+
*/
|
275
|
+
*res = T(f.out);
|
276
|
+
T(f.out) = 0;
|
277
|
+
S(f.out) = 0;
|
278
|
+
}
|
279
|
+
else {
|
280
|
+
*res = 0;
|
281
|
+
len = EOF;
|
282
|
+
}
|
283
|
+
___mkd_freemmiot(&f, 0);
|
284
|
+
return len;
|
285
|
+
}
|
286
|
+
|
287
|
+
|
288
|
+
/* ___mkd_reparse() a line, writing it to a FILE
|
289
|
+
*/
|
290
|
+
int
|
291
|
+
mkd_generateline(char *bfr, int size, FILE *output, int flags)
|
292
|
+
{
|
293
|
+
MMIOT f;
|
294
|
+
|
295
|
+
mkd_parse_line(bfr, size, &f, flags);
|
296
|
+
if ( flags & CDATA_OUTPUT )
|
297
|
+
mkd_generatexml(T(f.out), S(f.out), output);
|
298
|
+
else
|
299
|
+
fwrite(T(f.out), S(f.out), 1, output);
|
300
|
+
|
301
|
+
___mkd_freemmiot(&f, 0);
|
302
|
+
return 0;
|
303
|
+
}
|
data/ext/mkdio.h
CHANGED
@@ -15,19 +15,15 @@ void mkd_basename(MMIOT*,char*);
|
|
15
15
|
/* compilation, debugging, cleanup
|
16
16
|
*/
|
17
17
|
int mkd_compile(MMIOT*, int);
|
18
|
-
int mkd_generatehtml(MMIOT*,FILE*);
|
19
|
-
int mkd_generatetoc(MMIOT*,FILE*);
|
20
|
-
int mkd_xhtmlpage(MMIOT*,int,FILE*);
|
21
18
|
int mkd_cleanup(MMIOT*);
|
22
19
|
|
23
20
|
/* markup functions
|
24
21
|
*/
|
25
|
-
int mkd_text(char *, int, FILE*, int);
|
26
|
-
int mkd_style(MMIOT*, FILE*);
|
27
22
|
int mkd_dump(MMIOT*, FILE*, int, char*);
|
28
23
|
int markdown(MMIOT*, FILE*, int);
|
29
|
-
|
24
|
+
int mkd_line(char *, int, char **, int);
|
30
25
|
void mkd_string_to_anchor(char *, int, int (*)(int,void*), void*);
|
26
|
+
int mkd_xhtmlpage(MMIOT*,int,FILE*);
|
31
27
|
|
32
28
|
/* header block access
|
33
29
|
*/
|
@@ -38,6 +34,19 @@ char* mkd_doc_date(MMIOT*);
|
|
38
34
|
/* compiled data access
|
39
35
|
*/
|
40
36
|
int mkd_document(MMIOT*, char**);
|
37
|
+
int mkd_toc(MMIOT*, char**);
|
38
|
+
int mkd_css(MMIOT*, char **);
|
39
|
+
int mkd_xml(char *, int, char **);
|
40
|
+
|
41
|
+
/* write-to-file functions
|
42
|
+
*/
|
43
|
+
int mkd_generatehtml(MMIOT*,FILE*);
|
44
|
+
int mkd_generatetoc(MMIOT*,FILE*);
|
45
|
+
int mkd_generatexml(char *, int,FILE*);
|
46
|
+
int mkd_generatecss(MMIOT*,FILE*);
|
47
|
+
#define mkd_style mkd_generatecss
|
48
|
+
int mkd_generateline(char *, int, FILE*, int);
|
49
|
+
#define mkd_text mkd_generateline
|
41
50
|
|
42
51
|
/* version#.
|
43
52
|
*/
|
@@ -50,11 +59,15 @@ extern char markdown_version[];
|
|
50
59
|
#define MKD_NOPANTS 0x0004 /* don't run smartypants() */
|
51
60
|
#define MKD_NOHTML 0x0008 /* don't allow raw html through AT ALL */
|
52
61
|
#define MKD_STRICT 0x0010 /* disable SUPERSCRIPT, RELAXED_EMPHASIS */
|
53
|
-
#define MKD_TAGTEXT 0x0020 /*
|
62
|
+
#define MKD_TAGTEXT 0x0020 /* process text inside an html tag; no
|
63
|
+
* <em>, no <bold>, no html or [] expansion */
|
54
64
|
#define MKD_NO_EXT 0x0040 /* don't allow pseudo-protocols */
|
55
65
|
#define MKD_CDATA 0x0080 /* generate code for xml ![CDATA[...]] */
|
66
|
+
#define MKD_NOTABLES 0x0400 /* disallow tables */
|
56
67
|
#define MKD_TOC 0x1000 /* do table-of-contents processing */
|
57
68
|
#define MKD_1_COMPAT 0x2000 /* compatability with MarkdownTest_1.0 */
|
69
|
+
#define MKD_AUTOLINK 0x4000 /* make http://foo.com link even without <>s */
|
70
|
+
#define MKD_SAFELINK 0x8000 /* paranoid check for link protocol */
|
58
71
|
#define MKD_EMBED MKD_NOLINKS|MKD_NOIMAGE|MKD_TAGTEXT
|
59
72
|
|
60
73
|
/* special flags for mkd_in() and mkd_string()
|
data/ext/resource.c
CHANGED
@@ -55,6 +55,17 @@ ___mkd_freeParagraph(Paragraph *p)
|
|
55
55
|
}
|
56
56
|
|
57
57
|
|
58
|
+
/* bye bye footnote.
|
59
|
+
*/
|
60
|
+
void
|
61
|
+
___mkd_freefootnote(Footnote *f)
|
62
|
+
{
|
63
|
+
DELETE(f->tag);
|
64
|
+
DELETE(f->link);
|
65
|
+
DELETE(f->title);
|
66
|
+
}
|
67
|
+
|
68
|
+
|
58
69
|
/* bye bye footnotes.
|
59
70
|
*/
|
60
71
|
void
|
@@ -63,11 +74,8 @@ ___mkd_freefootnotes(MMIOT *f)
|
|
63
74
|
int i;
|
64
75
|
|
65
76
|
if ( f->footnotes ) {
|
66
|
-
for (i=0; i < S(*f->footnotes); i++)
|
67
|
-
|
68
|
-
DELETE(T(*f->footnotes)[i].link);
|
69
|
-
DELETE(T(*f->footnotes)[i].title);
|
70
|
-
}
|
77
|
+
for (i=0; i < S(*f->footnotes); i++)
|
78
|
+
___mkd_freefootnote( &T(*f->footnotes)[i] );
|
71
79
|
DELETE(*f->footnotes);
|
72
80
|
free(f->footnotes);
|
73
81
|
}
|
@@ -145,25 +153,3 @@ mkd_cleanup(Document *doc)
|
|
145
153
|
free(doc);
|
146
154
|
}
|
147
155
|
}
|
148
|
-
|
149
|
-
|
150
|
-
/* write output in XML format
|
151
|
-
*/
|
152
|
-
void
|
153
|
-
___mkd_xml(char *p, int size, FILE *out)
|
154
|
-
{
|
155
|
-
char c;
|
156
|
-
|
157
|
-
while ( size-- > 0 ) {
|
158
|
-
if ( !isascii(c = *p++) )
|
159
|
-
continue;
|
160
|
-
switch (c) {
|
161
|
-
case '<': fputs("<", out); break;
|
162
|
-
case '>': fputs(">", out); break;
|
163
|
-
case '&': fputs("&", out); break;
|
164
|
-
case '"': fputs(""", out); break;
|
165
|
-
case '\'':fputs("'", out); break;
|
166
|
-
default: putc(c,out); break;
|
167
|
-
}
|
168
|
-
}
|
169
|
-
}
|
data/ext/toc.c
CHANGED
@@ -19,7 +19,7 @@
|
|
19
19
|
int
|
20
20
|
mkd_toc(Document *p, char **doc)
|
21
21
|
{
|
22
|
-
Paragraph *
|
22
|
+
Paragraph *tp, *srcp;
|
23
23
|
int last_hnumber = 0;
|
24
24
|
Cstring res;
|
25
25
|
|
@@ -31,27 +31,31 @@ mkd_toc(Document *p, char **doc)
|
|
31
31
|
if ( !(p && p->ctx) ) return -1;
|
32
32
|
if ( ! (p->ctx->flags & TOC) ) return 0;
|
33
33
|
|
34
|
-
for (
|
35
|
-
|
34
|
+
for ( tp = p->code; tp ; tp = tp->next ) {
|
35
|
+
if ( tp->typ == SOURCE ) {
|
36
|
+
for ( srcp = tp->down; srcp; srcp = srcp->next ) {
|
37
|
+
if ( srcp->typ == HDR && srcp->text ) {
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
39
|
+
if ( last_hnumber == srcp->hnumber )
|
40
|
+
Csprintf(&res, "%*s</li>\n", srcp->hnumber, "");
|
41
|
+
else while ( last_hnumber > srcp->hnumber ) {
|
42
|
+
Csprintf(&res, "%*s</li>\n%*s</ul>\n",
|
43
|
+
last_hnumber, "",
|
44
|
+
last_hnumber-1,"");
|
45
|
+
--last_hnumber;
|
46
|
+
}
|
47
|
+
|
48
|
+
while ( srcp->hnumber > last_hnumber ) {
|
49
|
+
Csprintf(&res, "\n%*s<ul>\n", srcp->hnumber, "");
|
50
|
+
++last_hnumber;
|
51
|
+
}
|
52
|
+
Csprintf(&res, "%*s<li><a href=\"#", srcp->hnumber, "");
|
53
|
+
mkd_string_to_anchor(T(srcp->text->text), S(srcp->text->text), Csputc, &res);
|
54
|
+
Csprintf(&res, "\">");
|
55
|
+
Csreparse(&res, T(srcp->text->text), S(srcp->text->text), 0);
|
56
|
+
Csprintf(&res, "</a>");
|
57
|
+
}
|
49
58
|
}
|
50
|
-
Csprintf(&res, "%*s<li><a href=\"#", pp->hnumber, "");
|
51
|
-
mkd_string_to_anchor(T(pp->text->text), S(pp->text->text), Csputc, &res);
|
52
|
-
Csprintf(&res, "\">");
|
53
|
-
Csreparse(&res, T(pp->text->text), S(pp->text->text), 0);
|
54
|
-
Csprintf(&res, "</a>");
|
55
59
|
}
|
56
60
|
}
|
57
61
|
|
data/ext/xml.c
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
/* markdown: a C implementation of John Gruber's Markdown markup language.
|
2
|
+
*
|
3
|
+
* Copyright (C) 2007 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
|
+
/* return the xml version of a character
|
21
|
+
*/
|
22
|
+
static char *
|
23
|
+
mkd_xmlchar(unsigned char c)
|
24
|
+
{
|
25
|
+
switch (c) {
|
26
|
+
case '<': return "<";
|
27
|
+
case '>': return ">";
|
28
|
+
case '&': return "&";
|
29
|
+
case '"': return """;
|
30
|
+
case '\'': return "'";
|
31
|
+
default: if ( isascii(c) || (c & 0x80) )
|
32
|
+
return 0;
|
33
|
+
return "";
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
|
38
|
+
/* write output in XML format
|
39
|
+
*/
|
40
|
+
int
|
41
|
+
mkd_generatexml(char *p, int size, FILE *out)
|
42
|
+
{
|
43
|
+
unsigned char c;
|
44
|
+
char *entity;
|
45
|
+
|
46
|
+
while ( size-- > 0 ) {
|
47
|
+
c = *p++;
|
48
|
+
|
49
|
+
if ( entity = mkd_xmlchar(c) )
|
50
|
+
fputs(entity, out);
|
51
|
+
else
|
52
|
+
fputc(c, out);
|
53
|
+
}
|
54
|
+
return 0;
|
55
|
+
}
|
56
|
+
|
57
|
+
|
58
|
+
/* build a xml'ed version of a string
|
59
|
+
*/
|
60
|
+
int
|
61
|
+
mkd_xml(char *p, int size, char **res)
|
62
|
+
{
|
63
|
+
unsigned char c;
|
64
|
+
char *entity;
|
65
|
+
Cstring f;
|
66
|
+
|
67
|
+
CREATE(f);
|
68
|
+
RESERVE(f, 100);
|
69
|
+
|
70
|
+
while ( size-- > 0 ) {
|
71
|
+
c = *p++;
|
72
|
+
if ( entity = mkd_xmlchar(c) )
|
73
|
+
Cswrite(&f, entity, strlen(entity));
|
74
|
+
else
|
75
|
+
Csputc(c, &f);
|
76
|
+
}
|
77
|
+
/* HACK ALERT! HACK ALERT! HACK ALERT! */
|
78
|
+
*res = T(f); /* we know that a T(Cstring) is a character pointer */
|
79
|
+
/* so we can simply pick it up and carry it away, */
|
80
|
+
return S(f); /* leaving the husk of the Ctring on the stack */
|
81
|
+
/* END HACK ALERT */
|
82
|
+
}
|
data/lib/rdiscount.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# and passes the Markdown 1.0 test suite. The RDiscount extension makes
|
5
5
|
# the Discount processor available via a Ruby C Extension library.
|
6
6
|
#
|
7
|
-
#
|
7
|
+
# == Usage
|
8
8
|
#
|
9
9
|
# RDiscount implements the basic protocol popularized by RedCloth and adopted
|
10
10
|
# by BlueCloth:
|
@@ -12,7 +12,7 @@
|
|
12
12
|
# markdown = RDiscount.new("Hello World!")
|
13
13
|
# puts markdown.to_html
|
14
14
|
#
|
15
|
-
#
|
15
|
+
# == Replacing BlueCloth
|
16
16
|
#
|
17
17
|
# Inject RDiscount into your BlueCloth-using code by replacing your bluecloth
|
18
18
|
# require statements with the following:
|
data/rdiscount.gemspec
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'rdiscount'
|
3
|
-
s.version = '1.
|
3
|
+
s.version = '1.5.5'
|
4
4
|
s.summary = "Fast Implementation of Gruber's Markdown in C"
|
5
|
-
s.date = '2009-
|
5
|
+
s.date = '2009-11-13'
|
6
6
|
s.email = 'r@tomayko.com'
|
7
7
|
s.homepage = 'http://github.com/rtomayko/rdiscount'
|
8
8
|
s.has_rdoc = true
|
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
|
|
16
16
|
ext/Csio.c
|
17
17
|
ext/amalloc.h
|
18
18
|
ext/config.h
|
19
|
+
ext/css.c
|
19
20
|
ext/cstring.h
|
20
21
|
ext/docheader.c
|
21
22
|
ext/dumptree.c
|
@@ -28,6 +29,7 @@ Gem::Specification.new do |s|
|
|
28
29
|
ext/rdiscount.c
|
29
30
|
ext/resource.c
|
30
31
|
ext/toc.c
|
32
|
+
ext/xml.c
|
31
33
|
lib/markdown.rb
|
32
34
|
lib/rdiscount.rb
|
33
35
|
rdiscount.gemspec
|