rdiscountwl 1.0.0.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.
- 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
|