rdiscountwl 1.0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/BUILDING +151 -0
- data/COPYING +33 -0
- data/README.markdown +73 -0
- data/Rakefile +224 -0
- data/bin/rdiscount +13 -0
- data/ext/Csio.c +61 -0
- data/ext/VERSION +1 -0
- data/ext/amalloc.c +135 -0
- data/ext/amalloc.h +29 -0
- data/ext/basename.c +43 -0
- data/ext/blocktags +33 -0
- data/ext/config.h +25 -0
- data/ext/css.c +87 -0
- data/ext/cstring.h +77 -0
- data/ext/docheader.c +49 -0
- data/ext/dumptree.c +151 -0
- data/ext/emmatch.c +188 -0
- data/ext/extconf.rb +49 -0
- data/ext/flags.c +91 -0
- data/ext/generate.c +1865 -0
- data/ext/github_flavoured.c +100 -0
- data/ext/html5.c +22 -0
- data/ext/markdown.c +1361 -0
- data/ext/markdown.h +238 -0
- data/ext/mkdio.c +360 -0
- data/ext/mkdio.h +122 -0
- data/ext/mktags.c +89 -0
- data/ext/pgm_options.c +146 -0
- data/ext/pgm_options.h +9 -0
- data/ext/rdiscount.c +150 -0
- data/ext/resource.c +159 -0
- data/ext/setup.c +39 -0
- data/ext/tags.c +94 -0
- data/ext/tags.h +19 -0
- data/ext/toc.c +114 -0
- data/ext/version.c +13 -0
- data/ext/xml.c +82 -0
- data/ext/xmlpage.c +46 -0
- data/lib/markdown.rb +1 -0
- data/lib/rdiscount.rb +108 -0
- data/man/markdown.7 +1020 -0
- data/man/rdiscount.1 +22 -0
- data/man/rdiscount.1.ronn +24 -0
- data/rdiscount.gemspec +71 -0
- data/test/benchmark.rb +56 -0
- data/test/benchmark.txt +306 -0
- data/test/markdown_test.rb +158 -0
- data/test/rdiscount_test.rb +276 -0
- metadata +99 -0
data/ext/mktags.c
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
/* block-level tags for passing html blocks through the blender
|
2
|
+
*/
|
3
|
+
#include <stdio.h>
|
4
|
+
|
5
|
+
#define __WITHOUT_AMALLOC 1
|
6
|
+
#include "cstring.h"
|
7
|
+
#include "tags.h"
|
8
|
+
|
9
|
+
STRING(struct kw) blocktags;
|
10
|
+
|
11
|
+
|
12
|
+
/* define a html block tag
|
13
|
+
*/
|
14
|
+
static void
|
15
|
+
define_one_tag(char *id, int selfclose)
|
16
|
+
{
|
17
|
+
struct kw *p = &EXPAND(blocktags);
|
18
|
+
|
19
|
+
p->id = id;
|
20
|
+
p->size = strlen(id);
|
21
|
+
p->selfclose = selfclose;
|
22
|
+
}
|
23
|
+
|
24
|
+
|
25
|
+
/* case insensitive string sort (for qsort() and bsearch() of block tags)
|
26
|
+
*/
|
27
|
+
static int
|
28
|
+
casort(struct kw *a, struct kw *b)
|
29
|
+
{
|
30
|
+
if ( a->size != b->size )
|
31
|
+
return a->size - b->size;
|
32
|
+
return strncasecmp(a->id, b->id, b->size);
|
33
|
+
}
|
34
|
+
|
35
|
+
|
36
|
+
/* stupid cast to make gcc shut up about the function types being
|
37
|
+
* passed into qsort() and bsearch()
|
38
|
+
*/
|
39
|
+
typedef int (*stfu)(const void*,const void*);
|
40
|
+
|
41
|
+
|
42
|
+
/* load in the standard collection of html tags that markdown supports
|
43
|
+
*/
|
44
|
+
main()
|
45
|
+
{
|
46
|
+
int i;
|
47
|
+
|
48
|
+
#define KW(x) define_one_tag(x, 0)
|
49
|
+
#define SC(x) define_one_tag(x, 1)
|
50
|
+
|
51
|
+
KW("STYLE");
|
52
|
+
KW("SCRIPT");
|
53
|
+
KW("ADDRESS");
|
54
|
+
KW("BDO");
|
55
|
+
KW("BLOCKQUOTE");
|
56
|
+
KW("CENTER");
|
57
|
+
KW("DFN");
|
58
|
+
KW("DIV");
|
59
|
+
KW("OBJECT");
|
60
|
+
KW("H1");
|
61
|
+
KW("H2");
|
62
|
+
KW("H3");
|
63
|
+
KW("H4");
|
64
|
+
KW("H5");
|
65
|
+
KW("H6");
|
66
|
+
KW("LISTING");
|
67
|
+
KW("NOBR");
|
68
|
+
KW("UL");
|
69
|
+
KW("P");
|
70
|
+
KW("OL");
|
71
|
+
KW("DL");
|
72
|
+
KW("PLAINTEXT");
|
73
|
+
KW("PRE");
|
74
|
+
KW("TABLE");
|
75
|
+
KW("WBR");
|
76
|
+
KW("XMP");
|
77
|
+
SC("HR");
|
78
|
+
KW("IFRAME");
|
79
|
+
KW("MAP");
|
80
|
+
|
81
|
+
qsort(T(blocktags), S(blocktags), sizeof(struct kw), (stfu)casort);
|
82
|
+
|
83
|
+
printf("static struct kw blocktags[] = {\n");
|
84
|
+
for (i=0; i < S(blocktags); i++)
|
85
|
+
printf(" { \"%s\", %d, %d },\n", T(blocktags)[i].id, T(blocktags)[i].size, T(blocktags)[i].selfclose );
|
86
|
+
printf("};\n\n");
|
87
|
+
printf("#define NR_blocktags %d\n", S(blocktags));
|
88
|
+
exit(0);
|
89
|
+
}
|
data/ext/pgm_options.c
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
/* markdown: a C implementation of John Gruber's Markdown markup language.
|
2
|
+
*
|
3
|
+
* Copyright (C) 2007-2011 David L Parsons.
|
4
|
+
* The redistribution terms are provided in the COPYRIGHT file that must
|
5
|
+
* be distributed with this source code.
|
6
|
+
*/
|
7
|
+
|
8
|
+
#include <stdio.h>
|
9
|
+
#include <stdlib.h>
|
10
|
+
#include <limits.h>
|
11
|
+
#ifndef _MSC_VER
|
12
|
+
#include <unistd.h>
|
13
|
+
#endif
|
14
|
+
#include <mkdio.h>
|
15
|
+
#include <errno.h>
|
16
|
+
#include <string.h>
|
17
|
+
#include <stdarg.h>
|
18
|
+
|
19
|
+
#include "config.h"
|
20
|
+
#include "amalloc.h"
|
21
|
+
|
22
|
+
#if HAVE_LIBGEN_H
|
23
|
+
#include <libgen.h>
|
24
|
+
#endif
|
25
|
+
|
26
|
+
static struct _opt {
|
27
|
+
char *name;
|
28
|
+
char *desc;
|
29
|
+
int off;
|
30
|
+
int skip; /* this opt is a synonym */
|
31
|
+
int sayenable;
|
32
|
+
mkd_flag_t flag;
|
33
|
+
} opts[] = {
|
34
|
+
{ "tabstop", "default (4-space) tabstops", 0, 0, 1, MKD_TABSTOP },
|
35
|
+
{ "image", "images", 1, 0, 1, MKD_NOIMAGE },
|
36
|
+
{ "links", "links", 1, 0, 1, MKD_NOLINKS },
|
37
|
+
{ "relax", "emphasis inside words", 1, 1, 1, MKD_STRICT },
|
38
|
+
{ "strict", "emphasis inside words", 0, 0, 1, MKD_STRICT },
|
39
|
+
{ "tables", "tables", 1, 0, 1, MKD_NOTABLES },
|
40
|
+
{ "header", "pandoc-style headers", 1, 0, 1, MKD_NOHEADER },
|
41
|
+
{ "html", "raw html", 1, 0, 1, MKD_NOHTML },
|
42
|
+
{ "ext", "extended protocols", 1, 0, 1, MKD_NO_EXT },
|
43
|
+
{ "cdata", "generate cdata", 0, 0, 0, MKD_CDATA },
|
44
|
+
{ "smarty", "smartypants", 1, 0, 1, MKD_NOPANTS },
|
45
|
+
{ "pants", "smartypants", 1, 1, 1, MKD_NOPANTS },
|
46
|
+
{ "toc", "tables of contents", 0, 0, 1, MKD_TOC },
|
47
|
+
{ "autolink", "autolinking", 0, 0, 1, MKD_AUTOLINK },
|
48
|
+
{ "safelink", "safe links", 0, 0, 1, MKD_SAFELINK },
|
49
|
+
{ "strikethrough", "strikethrough", 1, 0, 1, MKD_NOSTRIKETHROUGH },
|
50
|
+
{ "del", "strikethrough", 1, 1, 1, MKD_NOSTRIKETHROUGH },
|
51
|
+
{ "superscript", "superscript", 1, 0, 1, MKD_NOSUPERSCRIPT },
|
52
|
+
{ "emphasis", "emphasis inside words", 0, 0, 1, MKD_NORELAXED },
|
53
|
+
{ "divquote", ">%class% blockquotes", 1, 0, 1, MKD_NODIVQUOTE },
|
54
|
+
{ "alphalist", "alpha lists", 1, 0, 1, MKD_NOALPHALIST },
|
55
|
+
{ "definitionlist","definition lists", 1, 0, 1, MKD_NODLIST },
|
56
|
+
{ "1.0", "markdown 1.0 compatibility", 0, 0, 1, MKD_1_COMPAT },
|
57
|
+
{ "footnotes", "markdown extra footnotes", 0, 0, 1, MKD_EXTRA_FOOTNOTE },
|
58
|
+
{ "footnote", "markdown extra footnotes", 0, 1, 1, MKD_EXTRA_FOOTNOTE },
|
59
|
+
{ "style", "extract style blocks", 1, 0, 1, MKD_NOSTYLE },
|
60
|
+
{ "dldiscount", "discount-style definition lists", 1, 0, 1, MKD_NODLDISCOUNT },
|
61
|
+
{ "dlextra", "extra-style definition lists", 0, 0, 1, MKD_DLEXTRA },
|
62
|
+
{ "fencedcode", "fenced code blocks", 0, 0, 1, MKD_FENCEDCODE },
|
63
|
+
{ "idanchor", "id= anchors in TOC", 0, 0, 1, MKD_IDANCHOR },
|
64
|
+
{ "githubtags", "permit - and _ in element names", 0, 0, 0, MKD_GITHUBTAGS },
|
65
|
+
{ "urlencodedanchor", "urlencode special chars in TOC links", 0, 0, 0, MKD_URLENCODEDANCHOR },
|
66
|
+
} ;
|
67
|
+
|
68
|
+
#define NR(x) (sizeof x / sizeof x[0])
|
69
|
+
|
70
|
+
|
71
|
+
typedef int (*stfu)(const void *, const void *);
|
72
|
+
|
73
|
+
int
|
74
|
+
sort_by_name(struct _opt *a, struct _opt *b)
|
75
|
+
{
|
76
|
+
return strcmp(a->name,b->name);
|
77
|
+
}
|
78
|
+
|
79
|
+
int
|
80
|
+
sort_by_flag(struct _opt *a, struct _opt *b)
|
81
|
+
{
|
82
|
+
return a->flag - b->flag;
|
83
|
+
}
|
84
|
+
|
85
|
+
|
86
|
+
void
|
87
|
+
show_flags(int byname)
|
88
|
+
{
|
89
|
+
int i;
|
90
|
+
|
91
|
+
if ( byname ) {
|
92
|
+
qsort(opts, NR(opts), sizeof(opts[0]), (stfu)sort_by_name);
|
93
|
+
|
94
|
+
for (i=0; i < NR(opts); i++)
|
95
|
+
if ( ! opts[i].skip )
|
96
|
+
fprintf(stderr, "%16s : %s\n", opts[i].name, opts[i].desc);
|
97
|
+
}
|
98
|
+
else {
|
99
|
+
qsort(opts, NR(opts), sizeof(opts[0]), (stfu)sort_by_flag);
|
100
|
+
|
101
|
+
for (i=0; i < NR(opts); i++)
|
102
|
+
if ( ! opts[i].skip ) {
|
103
|
+
fprintf(stderr, "%08lx : ", (long)opts[i].flag);
|
104
|
+
if ( opts[i].sayenable )
|
105
|
+
fprintf(stderr, opts[i].off ? "disable " : "enable ");
|
106
|
+
fprintf(stderr, "%s\n", opts[i].desc);
|
107
|
+
}
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
|
112
|
+
int
|
113
|
+
set_flag(mkd_flag_t *flags, char *optionstring)
|
114
|
+
{
|
115
|
+
int i;
|
116
|
+
int enable;
|
117
|
+
char *arg;
|
118
|
+
|
119
|
+
for ( arg = strtok(optionstring, ","); arg; arg = strtok(NULL, ",") ) {
|
120
|
+
if ( *arg == '+' || *arg == '-' )
|
121
|
+
enable = (*arg++ == '+') ? 1 : 0;
|
122
|
+
else if ( strncasecmp(arg, "no", 2) == 0 ) {
|
123
|
+
arg += 2;
|
124
|
+
enable = 0;
|
125
|
+
}
|
126
|
+
else
|
127
|
+
enable = 1;
|
128
|
+
|
129
|
+
for ( i=0; i < NR(opts); i++ )
|
130
|
+
if ( strcasecmp(arg, opts[i].name) == 0 )
|
131
|
+
break;
|
132
|
+
|
133
|
+
if ( i < NR(opts) ) {
|
134
|
+
if ( opts[i].off )
|
135
|
+
enable = !enable;
|
136
|
+
|
137
|
+
if ( enable )
|
138
|
+
*flags |= opts[i].flag;
|
139
|
+
else
|
140
|
+
*flags &= ~opts[i].flag;
|
141
|
+
}
|
142
|
+
else
|
143
|
+
return 0;
|
144
|
+
}
|
145
|
+
return 1;
|
146
|
+
}
|
data/ext/pgm_options.h
ADDED
data/ext/rdiscount.c
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <locale.h>
|
3
|
+
#include "ruby.h"
|
4
|
+
#include "mkdio.h"
|
5
|
+
|
6
|
+
typedef struct {
|
7
|
+
char *accessor_name;
|
8
|
+
int flag;
|
9
|
+
} AccessorFlagPair;
|
10
|
+
|
11
|
+
/*
|
12
|
+
* Maps accessor names on the RDiscount object to Discount flags.
|
13
|
+
*
|
14
|
+
* The following flags are handled specially:
|
15
|
+
* - MKD_TABSTOP: Always set.
|
16
|
+
* - MKD_NOHEADER: Always set.
|
17
|
+
* - MKD_DLEXTRA: Always set. (For compatibility with RDiscount 2.1.8 and earlier.)
|
18
|
+
* - MKD_FENCEDCODE: Always set. (For compatibility with RDiscount 2.1.8 and earlier.)
|
19
|
+
* - MKD_GITHUBTAGS: Always set. (For compatibility with RDiscount 2.1.8 and earlier.)
|
20
|
+
* - MKD_NOPANTS: Set unless the "smart" accessor returns true.
|
21
|
+
*
|
22
|
+
* See rb_rdiscount__get_flags() for the detailed implementation.
|
23
|
+
*/
|
24
|
+
static AccessorFlagPair ACCESSOR_2_FLAG[] = {
|
25
|
+
{ "filter_html", MKD_NOHTML },
|
26
|
+
{ "footnotes", MKD_EXTRA_FOOTNOTE },
|
27
|
+
{ "generate_toc", MKD_TOC },
|
28
|
+
{ "no_image", MKD_NOIMAGE },
|
29
|
+
{ "no_links", MKD_NOLINKS },
|
30
|
+
{ "no_tables", MKD_NOTABLES },
|
31
|
+
{ "strict", MKD_STRICT },
|
32
|
+
{ "autolink", MKD_AUTOLINK },
|
33
|
+
{ "safelink", MKD_SAFELINK },
|
34
|
+
{ "no_pseudo_protocols", MKD_NO_EXT },
|
35
|
+
{ "no_superscript", MKD_NOSUPERSCRIPT },
|
36
|
+
{ "no_strikethrough", MKD_NOSTRIKETHROUGH },
|
37
|
+
{ NULL, 0 } /* sentinel */
|
38
|
+
};
|
39
|
+
|
40
|
+
static VALUE rb_cRDiscount;
|
41
|
+
|
42
|
+
int rb_rdiscount__get_flags(VALUE ruby_obj)
|
43
|
+
{
|
44
|
+
AccessorFlagPair *entry;
|
45
|
+
|
46
|
+
/* compile flags */
|
47
|
+
int flags = MKD_TABSTOP | MKD_NOHEADER | MKD_DLEXTRA | MKD_FENCEDCODE | MKD_GITHUBTAGS;
|
48
|
+
|
49
|
+
/* The "smart" accessor turns OFF the MKD_NOPANTS flag. */
|
50
|
+
if ( rb_funcall(ruby_obj, rb_intern("smart"), 0) != Qtrue ) {
|
51
|
+
flags = flags | MKD_NOPANTS;
|
52
|
+
}
|
53
|
+
|
54
|
+
/* Handle standard flags declared in ACCESSOR_2_FLAG */
|
55
|
+
for ( entry = ACCESSOR_2_FLAG; entry->accessor_name; entry++ ) {
|
56
|
+
if ( rb_funcall(ruby_obj, rb_intern(entry->accessor_name), 0) == Qtrue ) {
|
57
|
+
flags = flags | entry->flag;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
return flags;
|
62
|
+
}
|
63
|
+
|
64
|
+
static VALUE
|
65
|
+
rb_rdiscount_to_html(int argc, VALUE *argv, VALUE self)
|
66
|
+
{
|
67
|
+
/* grab char pointer to markdown input text */
|
68
|
+
char *res;
|
69
|
+
int szres;
|
70
|
+
VALUE encoding;
|
71
|
+
VALUE text = rb_funcall(self, rb_intern("text"), 0);
|
72
|
+
VALUE buf = rb_str_buf_new(1024);
|
73
|
+
Check_Type(text, T_STRING);
|
74
|
+
|
75
|
+
int flags = rb_rdiscount__get_flags(self);
|
76
|
+
|
77
|
+
/*
|
78
|
+
* Force Discount to use ASCII character encoding for isalnum(), isalpha(),
|
79
|
+
* and similar functions.
|
80
|
+
*
|
81
|
+
* Ruby tends to use UTF-8 encoding, which is ill-defined for these
|
82
|
+
* functions since they expect 8-bit codepoints (and UTF-8 has codepoints
|
83
|
+
* of at least 21 bits).
|
84
|
+
*/
|
85
|
+
char *old_locale = strdup(setlocale(LC_CTYPE, NULL));
|
86
|
+
setlocale(LC_CTYPE, "C"); /* ASCII (and passthru characters > 127) */
|
87
|
+
|
88
|
+
MMIOT *doc = mkd_string(RSTRING_PTR(text), RSTRING_LEN(text), flags);
|
89
|
+
|
90
|
+
if ( mkd_compile(doc, flags) ) {
|
91
|
+
szres = mkd_document(doc, &res);
|
92
|
+
|
93
|
+
if ( szres != EOF ) {
|
94
|
+
rb_str_cat(buf, res, szres);
|
95
|
+
rb_str_cat(buf, "\n", 1);
|
96
|
+
}
|
97
|
+
}
|
98
|
+
mkd_cleanup(doc);
|
99
|
+
|
100
|
+
setlocale(LC_CTYPE, old_locale);
|
101
|
+
free(old_locale);
|
102
|
+
|
103
|
+
/* force the input encoding */
|
104
|
+
if ( rb_respond_to(text, rb_intern("encoding")) ) {
|
105
|
+
encoding = rb_funcall(text, rb_intern("encoding"), 0);
|
106
|
+
rb_funcall(buf, rb_intern("force_encoding"), 1, encoding);
|
107
|
+
}
|
108
|
+
|
109
|
+
return buf;
|
110
|
+
}
|
111
|
+
|
112
|
+
static VALUE
|
113
|
+
rb_rdiscount_toc_content(int argc, VALUE *argv, VALUE self)
|
114
|
+
{
|
115
|
+
char *res;
|
116
|
+
int szres;
|
117
|
+
|
118
|
+
int flags = rb_rdiscount__get_flags(self);
|
119
|
+
|
120
|
+
/* grab char pointer to markdown input text */
|
121
|
+
VALUE text = rb_funcall(self, rb_intern("text"), 0);
|
122
|
+
Check_Type(text, T_STRING);
|
123
|
+
|
124
|
+
/* allocate a ruby string buffer and wrap it in a stream */
|
125
|
+
VALUE buf = rb_str_buf_new(4096);
|
126
|
+
|
127
|
+
MMIOT *doc = mkd_string(RSTRING_PTR(text), RSTRING_LEN(text), flags);
|
128
|
+
|
129
|
+
if ( mkd_compile(doc, flags) ) {
|
130
|
+
szres = mkd_toc(doc, &res);
|
131
|
+
|
132
|
+
if ( szres != EOF ) {
|
133
|
+
rb_str_cat(buf, res, szres);
|
134
|
+
rb_str_cat(buf, "\n", 1);
|
135
|
+
}
|
136
|
+
}
|
137
|
+
mkd_cleanup(doc);
|
138
|
+
|
139
|
+
return buf;
|
140
|
+
}
|
141
|
+
|
142
|
+
|
143
|
+
void Init_rdiscount()
|
144
|
+
{
|
145
|
+
rb_cRDiscount = rb_define_class("RDiscount", rb_cObject);
|
146
|
+
rb_define_method(rb_cRDiscount, "to_html", rb_rdiscount_to_html, -1);
|
147
|
+
rb_define_method(rb_cRDiscount, "toc_content", rb_rdiscount_toc_content, -1);
|
148
|
+
}
|
149
|
+
|
150
|
+
/* vim: set ts=4 sw=4: */
|
data/ext/resource.c
ADDED
@@ -0,0 +1,159 @@
|
|
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
|
+
if (p->lang)
|
55
|
+
free(p->lang);
|
56
|
+
free(p);
|
57
|
+
}
|
58
|
+
|
59
|
+
|
60
|
+
/* bye bye footnote.
|
61
|
+
*/
|
62
|
+
void
|
63
|
+
___mkd_freefootnote(Footnote *f)
|
64
|
+
{
|
65
|
+
DELETE(f->tag);
|
66
|
+
DELETE(f->link);
|
67
|
+
DELETE(f->title);
|
68
|
+
}
|
69
|
+
|
70
|
+
|
71
|
+
/* bye bye footnotes.
|
72
|
+
*/
|
73
|
+
void
|
74
|
+
___mkd_freefootnotes(MMIOT *f)
|
75
|
+
{
|
76
|
+
int i;
|
77
|
+
|
78
|
+
if ( f->footnotes ) {
|
79
|
+
for (i=0; i < S(f->footnotes->note); i++)
|
80
|
+
___mkd_freefootnote( &T(f->footnotes->note)[i] );
|
81
|
+
DELETE(f->footnotes->note);
|
82
|
+
free(f->footnotes);
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
|
87
|
+
/* initialize a new MMIOT
|
88
|
+
*/
|
89
|
+
void
|
90
|
+
___mkd_initmmiot(MMIOT *f, void *footnotes)
|
91
|
+
{
|
92
|
+
if ( f ) {
|
93
|
+
memset(f, 0, sizeof *f);
|
94
|
+
CREATE(f->in);
|
95
|
+
CREATE(f->out);
|
96
|
+
CREATE(f->Q);
|
97
|
+
if ( footnotes )
|
98
|
+
f->footnotes = footnotes;
|
99
|
+
else {
|
100
|
+
f->footnotes = malloc(sizeof f->footnotes[0]);
|
101
|
+
CREATE(f->footnotes->note);
|
102
|
+
}
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
|
107
|
+
/* free the contents of a MMIOT, but leave the object alone.
|
108
|
+
*/
|
109
|
+
void
|
110
|
+
___mkd_freemmiot(MMIOT *f, void *footnotes)
|
111
|
+
{
|
112
|
+
if ( f ) {
|
113
|
+
DELETE(f->in);
|
114
|
+
DELETE(f->out);
|
115
|
+
DELETE(f->Q);
|
116
|
+
if ( f->footnotes != footnotes )
|
117
|
+
___mkd_freefootnotes(f);
|
118
|
+
memset(f, 0, sizeof *f);
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
|
123
|
+
/* free lines up to an barrier.
|
124
|
+
*/
|
125
|
+
void
|
126
|
+
___mkd_freeLineRange(Line *anchor, Line *stop)
|
127
|
+
{
|
128
|
+
Line *r = anchor->next;
|
129
|
+
|
130
|
+
if ( r != stop ) {
|
131
|
+
while ( r && (r->next != stop) )
|
132
|
+
r = r->next;
|
133
|
+
if ( r ) r->next = 0;
|
134
|
+
___mkd_freeLines(anchor->next);
|
135
|
+
}
|
136
|
+
anchor->next = 0;
|
137
|
+
}
|
138
|
+
|
139
|
+
|
140
|
+
/* clean up everything allocated in __mkd_compile()
|
141
|
+
*/
|
142
|
+
void
|
143
|
+
mkd_cleanup(Document *doc)
|
144
|
+
{
|
145
|
+
if ( doc && (doc->magic == VALID_DOCUMENT) ) {
|
146
|
+
if ( doc->ctx ) {
|
147
|
+
___mkd_freemmiot(doc->ctx, 0);
|
148
|
+
free(doc->ctx);
|
149
|
+
}
|
150
|
+
|
151
|
+
if ( doc->code) ___mkd_freeParagraph(doc->code);
|
152
|
+
if ( doc->title) ___mkd_freeLine(doc->title);
|
153
|
+
if ( doc->author) ___mkd_freeLine(doc->author);
|
154
|
+
if ( doc->date) ___mkd_freeLine(doc->date);
|
155
|
+
if ( T(doc->content) ) ___mkd_freeLines(T(doc->content));
|
156
|
+
memset(doc, 0, sizeof doc[0]);
|
157
|
+
free(doc);
|
158
|
+
}
|
159
|
+
}
|
data/ext/setup.c
ADDED
@@ -0,0 +1,39 @@
|
|
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 "config.h"
|
8
|
+
|
9
|
+
#include <stdio.h>
|
10
|
+
#include <string.h>
|
11
|
+
#include <stdarg.h>
|
12
|
+
#include <stdlib.h>
|
13
|
+
#include <time.h>
|
14
|
+
#include <ctype.h>
|
15
|
+
|
16
|
+
#include "cstring.h"
|
17
|
+
#include "markdown.h"
|
18
|
+
#include "amalloc.h"
|
19
|
+
#include "tags.h"
|
20
|
+
|
21
|
+
static int need_to_initrng = 1;
|
22
|
+
|
23
|
+
void
|
24
|
+
mkd_initialize()
|
25
|
+
{
|
26
|
+
|
27
|
+
if ( need_to_initrng ) {
|
28
|
+
need_to_initrng = 0;
|
29
|
+
INITRNG(time(0));
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
|
34
|
+
void
|
35
|
+
mkd_shlib_destructor()
|
36
|
+
{
|
37
|
+
mkd_deallocate_tags();
|
38
|
+
}
|
39
|
+
|
data/ext/tags.c
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
/* block-level tags for passing html blocks through the blender
|
2
|
+
*/
|
3
|
+
#define __WITHOUT_AMALLOC 1
|
4
|
+
#include "cstring.h"
|
5
|
+
#include "tags.h"
|
6
|
+
|
7
|
+
STRING(struct kw) extratags;
|
8
|
+
|
9
|
+
/* the standard collection of tags are built and sorted when
|
10
|
+
* discount is configured, so all we need to do is pull them
|
11
|
+
* in and use them.
|
12
|
+
*
|
13
|
+
* Additional tags still need to be allocated, sorted, and deallocated.
|
14
|
+
*/
|
15
|
+
#include "blocktags"
|
16
|
+
|
17
|
+
|
18
|
+
/* define an additional html block tag
|
19
|
+
*/
|
20
|
+
void
|
21
|
+
mkd_define_tag(char *id, int selfclose)
|
22
|
+
{
|
23
|
+
struct kw *p;
|
24
|
+
|
25
|
+
/* only add the new tag if it doesn't exist in
|
26
|
+
* either the standard or extra tag tables.
|
27
|
+
*/
|
28
|
+
if ( !(p = mkd_search_tags(id, strlen(id))) ) {
|
29
|
+
/* extratags could be deallocated */
|
30
|
+
if ( S(extratags) == 0 )
|
31
|
+
CREATE(extratags);
|
32
|
+
p = &EXPAND(extratags);
|
33
|
+
p->id = id;
|
34
|
+
p->size = strlen(id);
|
35
|
+
p->selfclose = selfclose;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
|
40
|
+
/* case insensitive string sort (for qsort() and bsearch() of block tags)
|
41
|
+
*/
|
42
|
+
static int
|
43
|
+
casort(struct kw *a, struct kw *b)
|
44
|
+
{
|
45
|
+
if ( a->size != b->size )
|
46
|
+
return a->size - b->size;
|
47
|
+
return strncasecmp(a->id, b->id, b->size);
|
48
|
+
}
|
49
|
+
|
50
|
+
|
51
|
+
/* stupid cast to make gcc shut up about the function types being
|
52
|
+
* passed into qsort() and bsearch()
|
53
|
+
*/
|
54
|
+
typedef int (*stfu)(const void*,const void*);
|
55
|
+
|
56
|
+
|
57
|
+
/* sort the list of extra html block tags for later searching
|
58
|
+
*/
|
59
|
+
void
|
60
|
+
mkd_sort_tags()
|
61
|
+
{
|
62
|
+
qsort(T(extratags), S(extratags), sizeof(struct kw), (stfu)casort);
|
63
|
+
}
|
64
|
+
|
65
|
+
|
66
|
+
/* look for a token in the html block tag list
|
67
|
+
*/
|
68
|
+
struct kw*
|
69
|
+
mkd_search_tags(char *pat, int len)
|
70
|
+
{
|
71
|
+
struct kw key;
|
72
|
+
struct kw *ret;
|
73
|
+
|
74
|
+
key.id = pat;
|
75
|
+
key.size = len;
|
76
|
+
|
77
|
+
if ( (ret=bsearch(&key,blocktags,NR_blocktags,sizeof key,(stfu)casort)) )
|
78
|
+
return ret;
|
79
|
+
|
80
|
+
if ( S(extratags) )
|
81
|
+
return bsearch(&key,T(extratags),S(extratags),sizeof key,(stfu)casort);
|
82
|
+
|
83
|
+
return 0;
|
84
|
+
}
|
85
|
+
|
86
|
+
|
87
|
+
/* destroy the extratags list (for shared libraries)
|
88
|
+
*/
|
89
|
+
void
|
90
|
+
mkd_deallocate_tags()
|
91
|
+
{
|
92
|
+
if ( S(extratags) > 0 )
|
93
|
+
DELETE(extratags);
|
94
|
+
} /* mkd_deallocate_tags */
|
data/ext/tags.h
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
/* block-level tags for passing html blocks through the blender
|
2
|
+
*/
|
3
|
+
#ifndef _TAGS_D
|
4
|
+
#define _TAGS_D
|
5
|
+
|
6
|
+
struct kw {
|
7
|
+
char *id;
|
8
|
+
int size;
|
9
|
+
int selfclose;
|
10
|
+
} ;
|
11
|
+
|
12
|
+
|
13
|
+
struct kw* mkd_search_tags(char *, int);
|
14
|
+
void mkd_prepare_tags();
|
15
|
+
void mkd_deallocate_tags();
|
16
|
+
void mkd_sort_tags();
|
17
|
+
void mkd_define_tag(char *, int);
|
18
|
+
|
19
|
+
#endif
|