chaptastic-rdiscount 1.4.1
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/COPYING +52 -0
- data/README.markdown +58 -0
- data/Rakefile +201 -0
- data/bin/rdiscount +5 -0
- data/ext/Csio.c +61 -0
- data/ext/amalloc.h +29 -0
- data/ext/config.h +9 -0
- data/ext/css.c +76 -0
- data/ext/cstring.h +74 -0
- data/ext/docheader.c +43 -0
- data/ext/dumptree.c +147 -0
- data/ext/extconf.rb +8 -0
- data/ext/generate.c +1457 -0
- data/ext/markdown.c +969 -0
- data/ext/markdown.h +145 -0
- data/ext/mkdio.c +303 -0
- data/ext/mkdio.h +78 -0
- data/ext/rdiscount.c +128 -0
- data/ext/resource.c +155 -0
- data/ext/toc.c +86 -0
- data/ext/xml.c +82 -0
- data/ext/xmlpage.c +48 -0
- data/lib/markdown.rb +1 -0
- data/lib/rdiscount.rb +95 -0
- data/rdiscount.gemspec +49 -0
- data/test/benchmark.rb +56 -0
- data/test/benchmark.txt +306 -0
- data/test/markdown_test.rb +119 -0
- data/test/rdiscount_test.rb +43 -0
- metadata +83 -0
data/ext/rdiscount.c
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include "ruby.h"
|
3
|
+
#include "mkdio.h"
|
4
|
+
|
5
|
+
static VALUE rb_cRDiscount;
|
6
|
+
|
7
|
+
static VALUE
|
8
|
+
rb_rdiscount_to_html(int argc, VALUE *argv, VALUE self)
|
9
|
+
{
|
10
|
+
/* grab char pointer to markdown input text */
|
11
|
+
char *res;
|
12
|
+
int szres;
|
13
|
+
VALUE text = rb_funcall(self, rb_intern("text"), 0);
|
14
|
+
VALUE buf = rb_str_buf_new(1024);
|
15
|
+
Check_Type(text, T_STRING);
|
16
|
+
|
17
|
+
int flags = rb_rdiscount__get_flags(self);
|
18
|
+
|
19
|
+
MMIOT *doc = mkd_string(RSTRING_PTR(text), RSTRING_LEN(text), flags);
|
20
|
+
|
21
|
+
if ( mkd_compile(doc, flags) ) {
|
22
|
+
szres = mkd_document(doc, &res);
|
23
|
+
|
24
|
+
if ( szres != EOF ) {
|
25
|
+
rb_str_cat(buf, res, szres);
|
26
|
+
rb_str_cat(buf, "\n", 1);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
mkd_cleanup(doc);
|
30
|
+
|
31
|
+
return buf;
|
32
|
+
}
|
33
|
+
|
34
|
+
static VALUE
|
35
|
+
rb_rdiscount_toc_content(int argc, VALUE *argv, VALUE self)
|
36
|
+
{
|
37
|
+
char *res;
|
38
|
+
int szres;
|
39
|
+
|
40
|
+
int flags = rb_rdiscount__get_flags(self);
|
41
|
+
|
42
|
+
/* grab char pointer to markdown input text */
|
43
|
+
VALUE text = rb_funcall(self, rb_intern("text"), 0);
|
44
|
+
Check_Type(text, T_STRING);
|
45
|
+
|
46
|
+
/* allocate a ruby string buffer and wrap it in a stream */
|
47
|
+
VALUE buf = rb_str_buf_new(4096);
|
48
|
+
|
49
|
+
MMIOT *doc = mkd_string(RSTRING_PTR(text), RSTRING_LEN(text), flags);
|
50
|
+
|
51
|
+
if ( mkd_compile(doc, flags) ) {
|
52
|
+
szres = mkd_toc(doc, &res);
|
53
|
+
|
54
|
+
if ( szres != EOF ) {
|
55
|
+
rb_str_cat(buf, res, szres);
|
56
|
+
rb_str_cat(buf, "\n", 1);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
mkd_cleanup(doc);
|
60
|
+
|
61
|
+
return buf;
|
62
|
+
}
|
63
|
+
|
64
|
+
int rb_rdiscount__get_flags(VALUE ruby_obj)
|
65
|
+
{
|
66
|
+
/* compile flags */
|
67
|
+
int flags = MKD_TABSTOP | MKD_NOHEADER;
|
68
|
+
|
69
|
+
/* no links */
|
70
|
+
if ( rb_funcall(ruby_obj, rb_intern("no_links"), 0) == Qtrue)
|
71
|
+
flags = flags | MKD_NOLINKS;
|
72
|
+
|
73
|
+
/* no images */
|
74
|
+
if ( rb_funcall(ruby_obj, rb_intern("no_image"), 0) == Qtrue)
|
75
|
+
flags = flags | MKD_NOIMAGE;
|
76
|
+
|
77
|
+
/* smart */
|
78
|
+
if ( rb_funcall(ruby_obj, rb_intern("smart"), 0) != Qtrue )
|
79
|
+
flags = flags | MKD_NOPANTS;
|
80
|
+
|
81
|
+
/* filter_html */
|
82
|
+
if ( rb_funcall(ruby_obj, rb_intern("filter_html"), 0) == Qtrue )
|
83
|
+
flags = flags | MKD_NOHTML;
|
84
|
+
|
85
|
+
/* disable SUPERSCRIPT and RELAXED_EMPAHSIS */
|
86
|
+
if ( rb_funcall(ruby_obj, rb_intern("strict"), 0) == Qtrue)
|
87
|
+
flags = flags | MKD_STRICT;
|
88
|
+
|
89
|
+
/* process text inside of tags */
|
90
|
+
if ( rb_funcall(ruby_obj, rb_intern("tagtext"), 0) == Qtrue)
|
91
|
+
flags = flags | MKD_TAGTEXT;
|
92
|
+
|
93
|
+
/* don't allow pseudo-protocols */
|
94
|
+
if ( rb_funcall(ruby_obj, rb_intern("no_ext"), 0) == Qtrue)
|
95
|
+
flags = flags | MKD_NO_EXT;
|
96
|
+
|
97
|
+
/* output for XML */
|
98
|
+
if ( rb_funcall(ruby_obj, rb_intern("cdata"), 0) == Qtrue)
|
99
|
+
flags = flags | MKD_CDATA;
|
100
|
+
|
101
|
+
/* generate_toc */
|
102
|
+
if ( rb_funcall(ruby_obj, rb_intern("generate_toc"), 0) == Qtrue)
|
103
|
+
flags = flags | MKD_TOC;
|
104
|
+
|
105
|
+
/* MarkdownTest_1.0 compatibility */
|
106
|
+
if ( rb_funcall(ruby_obj, rb_intern("one_compat"), 0) == Qtrue)
|
107
|
+
flags = flags | MKD_1_COMPAT;
|
108
|
+
|
109
|
+
/* autolinks */
|
110
|
+
if ( rb_funcall(ruby_obj, rb_intern("auto_link"), 0) == Qtrue)
|
111
|
+
flags = flags | MKD_AUTOLINK;
|
112
|
+
|
113
|
+
/* paranoid link protocols */
|
114
|
+
if ( rb_funcall(ruby_obj, rb_intern("safe_links"), 0) == Qtrue)
|
115
|
+
flags = flags | MKD_SAFELINK;
|
116
|
+
|
117
|
+
return flags;
|
118
|
+
}
|
119
|
+
|
120
|
+
|
121
|
+
void Init_rdiscount()
|
122
|
+
{
|
123
|
+
rb_cRDiscount = rb_define_class("RDiscount", rb_cObject);
|
124
|
+
rb_define_method(rb_cRDiscount, "to_html", rb_rdiscount_to_html, -1);
|
125
|
+
rb_define_method(rb_cRDiscount, "toc_content", rb_rdiscount_toc_content, -1);
|
126
|
+
}
|
127
|
+
|
128
|
+
/* vim: set ts=4 sw=4: */
|
data/ext/resource.c
ADDED
@@ -0,0 +1,155 @@
|
|
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
|
+
/* free a (single) line
|
21
|
+
*/
|
22
|
+
void
|
23
|
+
___mkd_freeLine(Line *ptr)
|
24
|
+
{
|
25
|
+
DELETE(ptr->text);
|
26
|
+
free(ptr);
|
27
|
+
}
|
28
|
+
|
29
|
+
|
30
|
+
/* free a list of lines
|
31
|
+
*/
|
32
|
+
void
|
33
|
+
___mkd_freeLines(Line *p)
|
34
|
+
{
|
35
|
+
if (p->next)
|
36
|
+
___mkd_freeLines(p->next);
|
37
|
+
___mkd_freeLine(p);
|
38
|
+
}
|
39
|
+
|
40
|
+
|
41
|
+
/* bye bye paragraph.
|
42
|
+
*/
|
43
|
+
void
|
44
|
+
___mkd_freeParagraph(Paragraph *p)
|
45
|
+
{
|
46
|
+
if (p->next)
|
47
|
+
___mkd_freeParagraph(p->next);
|
48
|
+
if (p->down)
|
49
|
+
___mkd_freeParagraph(p->down);
|
50
|
+
if (p->text)
|
51
|
+
___mkd_freeLines(p->text);
|
52
|
+
if (p->ident)
|
53
|
+
free(p->ident);
|
54
|
+
free(p);
|
55
|
+
}
|
56
|
+
|
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
|
+
|
69
|
+
/* bye bye footnotes.
|
70
|
+
*/
|
71
|
+
void
|
72
|
+
___mkd_freefootnotes(MMIOT *f)
|
73
|
+
{
|
74
|
+
int i;
|
75
|
+
|
76
|
+
if ( f->footnotes ) {
|
77
|
+
for (i=0; i < S(*f->footnotes); i++)
|
78
|
+
___mkd_freefootnote( &T(*f->footnotes)[i] );
|
79
|
+
DELETE(*f->footnotes);
|
80
|
+
free(f->footnotes);
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
|
85
|
+
/* initialize a new MMIOT
|
86
|
+
*/
|
87
|
+
void
|
88
|
+
___mkd_initmmiot(MMIOT *f, void *footnotes)
|
89
|
+
{
|
90
|
+
if ( f ) {
|
91
|
+
memset(f, 0, sizeof *f);
|
92
|
+
CREATE(f->in);
|
93
|
+
CREATE(f->out);
|
94
|
+
CREATE(f->Q);
|
95
|
+
if ( footnotes )
|
96
|
+
f->footnotes = footnotes;
|
97
|
+
else {
|
98
|
+
f->footnotes = malloc(sizeof f->footnotes[0]);
|
99
|
+
CREATE(*f->footnotes);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
|
105
|
+
/* free the contents of a MMIOT, but leave the object alone.
|
106
|
+
*/
|
107
|
+
void
|
108
|
+
___mkd_freemmiot(MMIOT *f, void *footnotes)
|
109
|
+
{
|
110
|
+
if ( f ) {
|
111
|
+
DELETE(f->in);
|
112
|
+
DELETE(f->out);
|
113
|
+
DELETE(f->Q);
|
114
|
+
if ( f->footnotes != footnotes )
|
115
|
+
___mkd_freefootnotes(f);
|
116
|
+
memset(f, 0, sizeof *f);
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
|
121
|
+
/* free lines up to an barrier.
|
122
|
+
*/
|
123
|
+
void
|
124
|
+
___mkd_freeLineRange(Line *anchor, Line *stop)
|
125
|
+
{
|
126
|
+
Line *r = anchor->next;
|
127
|
+
|
128
|
+
if ( r != stop ) {
|
129
|
+
while ( r && (r->next != stop) )
|
130
|
+
r = r->next;
|
131
|
+
if ( r ) r->next = 0;
|
132
|
+
___mkd_freeLines(anchor->next);
|
133
|
+
}
|
134
|
+
anchor->next = 0;
|
135
|
+
}
|
136
|
+
|
137
|
+
|
138
|
+
/* clean up everything allocated in __mkd_compile()
|
139
|
+
*/
|
140
|
+
void
|
141
|
+
mkd_cleanup(Document *doc)
|
142
|
+
{
|
143
|
+
if ( doc ) {
|
144
|
+
if ( doc->ctx ) {
|
145
|
+
___mkd_freemmiot(doc->ctx, 0);
|
146
|
+
free(doc->ctx);
|
147
|
+
}
|
148
|
+
|
149
|
+
if ( doc->code) ___mkd_freeParagraph(doc->code);
|
150
|
+
if ( doc->headers ) ___mkd_freeLines(doc->headers);
|
151
|
+
if ( T(doc->content) ) ___mkd_freeLines(T(doc->content));
|
152
|
+
memset(doc, 0, sizeof doc[0]);
|
153
|
+
free(doc);
|
154
|
+
}
|
155
|
+
}
|
data/ext/toc.c
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
/*
|
2
|
+
* toc -- spit out a table of contents based on header blocks
|
3
|
+
*
|
4
|
+
* Copyright (C) 2008 Jjgod Jiang, 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 "cstring.h"
|
14
|
+
#include "markdown.h"
|
15
|
+
#include "amalloc.h"
|
16
|
+
|
17
|
+
/* write an header index
|
18
|
+
*/
|
19
|
+
int
|
20
|
+
mkd_toc(Document *p, char **doc)
|
21
|
+
{
|
22
|
+
Paragraph *pp;
|
23
|
+
int last_hnumber = 0;
|
24
|
+
Cstring res;
|
25
|
+
|
26
|
+
CREATE(res);
|
27
|
+
RESERVE(res, 100);
|
28
|
+
|
29
|
+
*doc = 0;
|
30
|
+
|
31
|
+
if ( !(p && p->ctx) ) return -1;
|
32
|
+
if ( ! (p->ctx->flags & TOC) ) return 0;
|
33
|
+
|
34
|
+
for ( pp = p->code; pp ; pp = pp->next ) {
|
35
|
+
if ( pp->typ == HDR && pp->text ) {
|
36
|
+
|
37
|
+
if ( last_hnumber == pp->hnumber )
|
38
|
+
Csprintf(&res, "%*s</li>\n", pp->hnumber, "");
|
39
|
+
else while ( last_hnumber > pp->hnumber ) {
|
40
|
+
Csprintf(&res, "%*s</li>\n%*s</ul>\n",
|
41
|
+
last_hnumber, "",
|
42
|
+
last_hnumber-1,"");
|
43
|
+
--last_hnumber;
|
44
|
+
}
|
45
|
+
|
46
|
+
while ( pp->hnumber > last_hnumber ) {
|
47
|
+
Csprintf(&res, "\n%*s<ul>\n", pp->hnumber, "");
|
48
|
+
++last_hnumber;
|
49
|
+
}
|
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
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
while ( last_hnumber > 0 ) {
|
59
|
+
Csprintf(&res, "%*s</li>\n%*s</ul>\n",
|
60
|
+
last_hnumber, "", last_hnumber, "");
|
61
|
+
--last_hnumber;
|
62
|
+
}
|
63
|
+
/* HACK ALERT! HACK ALERT! HACK ALERT! */
|
64
|
+
*doc = T(res); /* we know that a T(Cstring) is a character pointer */
|
65
|
+
/* so we can simply pick it up and carry it away, */
|
66
|
+
return S(res); /* leaving the husk of the Ctring on the stack */
|
67
|
+
/* END HACK ALERT */
|
68
|
+
}
|
69
|
+
|
70
|
+
|
71
|
+
/* write an header index
|
72
|
+
*/
|
73
|
+
int
|
74
|
+
mkd_generatetoc(Document *p, FILE *out)
|
75
|
+
{
|
76
|
+
char *buf = 0;
|
77
|
+
int sz = mkd_toc(p, &buf);
|
78
|
+
int ret = EOF;
|
79
|
+
|
80
|
+
if ( sz > 0 )
|
81
|
+
ret = fwrite(buf, sz, 1, out);
|
82
|
+
|
83
|
+
if ( buf ) free(buf);
|
84
|
+
|
85
|
+
return ret;
|
86
|
+
}
|
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
|
+
}
|