vkhater-redcarpet 2.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,138 @@
1
+ /* markdown.h - generic markdown parser */
2
+
3
+ /*
4
+ * Copyright (c) 2009, Natacha Porté
5
+ *
6
+ * Permission to use, copy, modify, and distribute this software for any
7
+ * purpose with or without fee is hereby granted, provided that the above
8
+ * copyright notice and this permission notice appear in all copies.
9
+ *
10
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
+ */
18
+
19
+ #ifndef UPSKIRT_MARKDOWN_H
20
+ #define UPSKIRT_MARKDOWN_H
21
+
22
+ #include "buffer.h"
23
+ #include "autolink.h"
24
+
25
+ #ifdef __cplusplus
26
+ extern "C" {
27
+ #endif
28
+
29
+ #define SUNDOWN_VERSION "1.16.0"
30
+ #define SUNDOWN_VER_MAJOR 1
31
+ #define SUNDOWN_VER_MINOR 16
32
+ #define SUNDOWN_VER_REVISION 0
33
+
34
+ /********************
35
+ * TYPE DEFINITIONS *
36
+ ********************/
37
+
38
+ /* mkd_autolink - type of autolink */
39
+ enum mkd_autolink {
40
+ MKDA_NOT_AUTOLINK, /* used internally when it is not an autolink*/
41
+ MKDA_NORMAL, /* normal http/http/ftp/mailto/etc link */
42
+ MKDA_EMAIL, /* e-mail link without explit mailto: */
43
+ };
44
+
45
+ enum mkd_tableflags {
46
+ MKD_TABLE_ALIGN_L = 1,
47
+ MKD_TABLE_ALIGN_R = 2,
48
+ MKD_TABLE_ALIGN_CENTER = 3,
49
+ MKD_TABLE_ALIGNMASK = 3,
50
+ MKD_TABLE_HEADER = 4
51
+ };
52
+
53
+ enum mkd_extensions {
54
+ MKDEXT_NO_INTRA_EMPHASIS = (1 << 0),
55
+ MKDEXT_TABLES = (1 << 1),
56
+ MKDEXT_FENCED_CODE = (1 << 2),
57
+ MKDEXT_AUTOLINK = (1 << 3),
58
+ MKDEXT_STRIKETHROUGH = (1 << 4),
59
+ MKDEXT_SPACE_HEADERS = (1 << 6),
60
+ MKDEXT_SUPERSCRIPT = (1 << 7),
61
+ MKDEXT_LAX_SPACING = (1 << 8),
62
+ };
63
+
64
+ /* sd_callbacks - functions for rendering parsed data */
65
+ struct sd_callbacks {
66
+ /* block level callbacks - NULL skips the block */
67
+ void (*blockcode)(struct buf *ob, const struct buf *text, const struct buf *lang, void *opaque);
68
+ void (*blockquote)(struct buf *ob, const struct buf *text, void *opaque);
69
+ void (*blockhtml)(struct buf *ob,const struct buf *text, void *opaque);
70
+ void (*header)(struct buf *ob, const struct buf *text, int level, void *opaque);
71
+ void (*hrule)(struct buf *ob, void *opaque);
72
+ void (*list)(struct buf *ob, const struct buf *text, int flags, void *opaque);
73
+ void (*listitem)(struct buf *ob, const struct buf *text, int flags, void *opaque);
74
+ void (*paragraph)(struct buf *ob, const struct buf *text, void *opaque);
75
+ void (*table)(struct buf *ob, const struct buf *header, const struct buf *body, void *opaque);
76
+ void (*table_row)(struct buf *ob, const struct buf *text, void *opaque);
77
+ void (*table_cell)(struct buf *ob, const struct buf *text, int flags, void *opaque);
78
+
79
+
80
+ /* span level callbacks - NULL or return 0 prints the span verbatim */
81
+ int (*autolink)(struct buf *ob, const struct buf *link, enum mkd_autolink type, void *opaque);
82
+ int (*codespan)(struct buf *ob, const struct buf *text, void *opaque);
83
+ int (*double_emphasis)(struct buf *ob, const struct buf *text, void *opaque);
84
+ int (*emphasis)(struct buf *ob, const struct buf *text, void *opaque);
85
+ int (*image)(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *alt, void *opaque);
86
+ int (*linebreak)(struct buf *ob, void *opaque);
87
+ int (*link)(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *content, void *opaque);
88
+ int (*raw_html_tag)(struct buf *ob, const struct buf *tag, void *opaque);
89
+ int (*triple_emphasis)(struct buf *ob, const struct buf *text, void *opaque);
90
+ int (*strikethrough)(struct buf *ob, const struct buf *text, void *opaque);
91
+ int (*superscript)(struct buf *ob, const struct buf *text, void *opaque);
92
+
93
+ /* low level callbacks - NULL copies input directly into the output */
94
+ void (*entity)(struct buf *ob, const struct buf *entity, void *opaque);
95
+ void (*normal_text)(struct buf *ob, const struct buf *text, void *opaque);
96
+
97
+ /* header and footer */
98
+ void (*doc_header)(struct buf *ob, void *opaque);
99
+ void (*doc_footer)(struct buf *ob, void *opaque);
100
+ };
101
+
102
+ struct sd_markdown;
103
+
104
+ /*********
105
+ * FLAGS *
106
+ *********/
107
+
108
+ /* list/listitem flags */
109
+ #define MKD_LIST_ORDERED 1
110
+ #define MKD_LI_BLOCK 2 /* <li> containing block data */
111
+
112
+ /**********************
113
+ * EXPORTED FUNCTIONS *
114
+ **********************/
115
+
116
+ extern struct sd_markdown *
117
+ sd_markdown_new(
118
+ unsigned int extensions,
119
+ size_t max_nesting,
120
+ const struct sd_callbacks *callbacks,
121
+ void *opaque);
122
+
123
+ extern void
124
+ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, struct sd_markdown *md);
125
+
126
+ extern void
127
+ sd_markdown_free(struct sd_markdown *md);
128
+
129
+ extern void
130
+ sd_version(int *major, int *minor, int *revision);
131
+
132
+ #ifdef __cplusplus
133
+ }
134
+ #endif
135
+
136
+ #endif
137
+
138
+ /* vim: set filetype=c: */
@@ -0,0 +1,149 @@
1
+ /*
2
+ * Copyright (c) 2011, Vicent Marti
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+ #include "redcarpet.h"
17
+
18
+ VALUE rb_mRedcarpet;
19
+ VALUE rb_cMarkdown;
20
+
21
+ extern VALUE rb_cRenderBase;
22
+
23
+ static void rb_redcarpet_md_flags(VALUE hash, unsigned int *enabled_extensions_p)
24
+ {
25
+ unsigned int extensions = 0;
26
+
27
+ Check_Type(hash, T_HASH);
28
+
29
+ /**
30
+ * Markdown extensions -- all disabled by default
31
+ */
32
+ if (rb_hash_lookup(hash, CSTR2SYM("no_intra_emphasis")) == Qtrue)
33
+ extensions |= MKDEXT_NO_INTRA_EMPHASIS;
34
+
35
+ if (rb_hash_lookup(hash, CSTR2SYM("tables")) == Qtrue)
36
+ extensions |= MKDEXT_TABLES;
37
+
38
+ if (rb_hash_lookup(hash, CSTR2SYM("fenced_code_blocks")) == Qtrue)
39
+ extensions |= MKDEXT_FENCED_CODE;
40
+
41
+ if (rb_hash_lookup(hash, CSTR2SYM("autolink")) == Qtrue)
42
+ extensions |= MKDEXT_AUTOLINK;
43
+
44
+ if (rb_hash_lookup(hash, CSTR2SYM("strikethrough")) == Qtrue)
45
+ extensions |= MKDEXT_STRIKETHROUGH;
46
+
47
+ if (rb_hash_lookup(hash, CSTR2SYM("lax_spacing")) == Qtrue)
48
+ extensions |= MKDEXT_LAX_SPACING;
49
+
50
+ if (rb_hash_lookup(hash, CSTR2SYM("space_after_headers")) == Qtrue)
51
+ extensions |= MKDEXT_SPACE_HEADERS;
52
+
53
+ if (rb_hash_lookup(hash, CSTR2SYM("superscript")) == Qtrue)
54
+ extensions |= MKDEXT_SUPERSCRIPT;
55
+
56
+ *enabled_extensions_p = extensions;
57
+ }
58
+
59
+ static void
60
+ rb_redcarpet_md__free(void *markdown)
61
+ {
62
+ sd_markdown_free((struct sd_markdown *)markdown);
63
+ }
64
+
65
+ static VALUE rb_redcarpet_md__new(int argc, VALUE *argv, VALUE klass)
66
+ {
67
+ VALUE rb_markdown, rb_rndr, hash;
68
+ unsigned int extensions = 0;
69
+
70
+ struct rb_redcarpet_rndr *rndr;
71
+ struct sd_markdown *markdown;
72
+
73
+ if (rb_scan_args(argc, argv, "11", &rb_rndr, &hash) == 2)
74
+ rb_redcarpet_md_flags(hash, &extensions);
75
+
76
+ if (rb_obj_is_kind_of(rb_rndr, rb_cClass))
77
+ rb_rndr = rb_funcall(rb_rndr, rb_intern("new"), 0);
78
+
79
+ if (!rb_obj_is_kind_of(rb_rndr, rb_cRenderBase))
80
+ rb_raise(rb_eTypeError, "Invalid Renderer instance given");
81
+
82
+ Data_Get_Struct(rb_rndr, struct rb_redcarpet_rndr, rndr);
83
+
84
+ markdown = sd_markdown_new(extensions, 16, &rndr->callbacks, &rndr->options);
85
+ if (!markdown)
86
+ rb_raise(rb_eRuntimeError, "Failed to create new Renderer class");
87
+
88
+ rb_markdown = Data_Wrap_Struct(klass, NULL, rb_redcarpet_md__free, markdown);
89
+ rb_iv_set(rb_markdown, "@renderer", rb_rndr);
90
+
91
+ return rb_markdown;
92
+ }
93
+
94
+ static VALUE rb_redcarpet_md_render(VALUE self, VALUE text)
95
+ {
96
+ VALUE rb_rndr;
97
+ struct buf *output_buf;
98
+ struct sd_markdown *markdown;
99
+
100
+ Check_Type(text, T_STRING);
101
+
102
+ rb_rndr = rb_iv_get(self, "@renderer");
103
+ Data_Get_Struct(self, struct sd_markdown, markdown);
104
+
105
+ if (rb_respond_to(rb_rndr, rb_intern("preprocess")))
106
+ text = rb_funcall(rb_rndr, rb_intern("preprocess"), 1, text);
107
+ if (NIL_P(text))
108
+ return Qnil;
109
+
110
+ #ifdef HAVE_RUBY_ENCODING_H
111
+ {
112
+ struct rb_redcarpet_rndr *renderer;
113
+ Data_Get_Struct(rb_rndr, struct rb_redcarpet_rndr, renderer);
114
+ renderer->options.active_enc = rb_enc_get(text);
115
+ }
116
+ #endif
117
+
118
+ /* initialize buffers */
119
+ output_buf = bufnew(128);
120
+
121
+ /* render the magic */
122
+ sd_markdown_render(
123
+ output_buf,
124
+ RSTRING_PTR(text),
125
+ RSTRING_LEN(text),
126
+ markdown);
127
+
128
+ /* build the Ruby string */
129
+ text = redcarpet_str_new(output_buf->data, output_buf->size, rb_enc_get(text));
130
+
131
+ bufrelease(output_buf);
132
+
133
+ if (rb_respond_to(rb_rndr, rb_intern("postprocess")))
134
+ text = rb_funcall(rb_rndr, rb_intern("postprocess"), 1, text);
135
+
136
+ return text;
137
+ }
138
+
139
+ void Init_redcarpet()
140
+ {
141
+ rb_mRedcarpet = rb_define_module("Redcarpet");
142
+
143
+ rb_cMarkdown = rb_define_class_under(rb_mRedcarpet, "Markdown", rb_cObject);
144
+ rb_define_singleton_method(rb_cMarkdown, "new", rb_redcarpet_md__new, -1);
145
+ rb_define_method(rb_cMarkdown, "render", rb_redcarpet_md_render, 1);
146
+
147
+ Init_redcarpet_rndr();
148
+ }
149
+
@@ -0,0 +1,469 @@
1
+ /*
2
+ * Copyright (c) 2011, Vicent Marti
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+
17
+ #include "redcarpet.h"
18
+
19
+ #define SPAN_CALLBACK(method_name, ...) {\
20
+ struct redcarpet_renderopt *opt = opaque;\
21
+ VALUE ret = rb_funcall(opt->self, rb_intern(method_name), __VA_ARGS__);\
22
+ if (NIL_P(ret)) return 0;\
23
+ Check_Type(ret, T_STRING);\
24
+ bufput(ob, RSTRING_PTR(ret), RSTRING_LEN(ret));\
25
+ return 1;\
26
+ }
27
+
28
+ #define BLOCK_CALLBACK(method_name, ...) {\
29
+ struct redcarpet_renderopt *opt = opaque;\
30
+ VALUE ret = rb_funcall(opt->self, rb_intern(method_name), __VA_ARGS__);\
31
+ if (NIL_P(ret)) return;\
32
+ Check_Type(ret, T_STRING);\
33
+ bufput(ob, RSTRING_PTR(ret), RSTRING_LEN(ret));\
34
+ }
35
+
36
+ extern VALUE rb_mRedcarpet;
37
+ VALUE rb_mRender;
38
+ VALUE rb_cRenderBase;
39
+ VALUE rb_cRenderHTML;
40
+ VALUE rb_cRenderHTML_TOC;
41
+ VALUE rb_mSmartyPants;
42
+
43
+ #ifdef HAVE_RUBY_ENCODING_H
44
+ #define buf2str(t) ((t) ? redcarpet_str_new((t)->data, (t)->size, opt->active_enc) : Qnil)
45
+ #else
46
+ #define buf2str(t) ((t) ? redcarpet_str_new((t)->data, (t)->size, NULL) : Qnil)
47
+ #endif
48
+
49
+ static void
50
+ rndr_blockcode(struct buf *ob, const struct buf *text, const struct buf *lang, void *opaque)
51
+ {
52
+ BLOCK_CALLBACK("block_code", 2, buf2str(text), buf2str(lang));
53
+ }
54
+
55
+ static void
56
+ rndr_blockquote(struct buf *ob, const struct buf *text, void *opaque)
57
+ {
58
+ BLOCK_CALLBACK("block_quote", 1, buf2str(text));
59
+ }
60
+
61
+ static void
62
+ rndr_raw_block(struct buf *ob, const struct buf *text, void *opaque)
63
+ {
64
+ BLOCK_CALLBACK("block_html", 1, buf2str(text));
65
+ }
66
+
67
+ static void
68
+ rndr_header(struct buf *ob, const struct buf *text, int level, void *opaque)
69
+ {
70
+ BLOCK_CALLBACK("header", 2, buf2str(text), INT2FIX(level));
71
+ }
72
+
73
+ static void
74
+ rndr_hrule(struct buf *ob, void *opaque)
75
+ {
76
+ BLOCK_CALLBACK("hrule", 0);
77
+ }
78
+
79
+ static void
80
+ rndr_list(struct buf *ob, const struct buf *text, int flags, void *opaque)
81
+ {
82
+ BLOCK_CALLBACK("list", 2, buf2str(text),
83
+ (flags & MKD_LIST_ORDERED) ? CSTR2SYM("ordered") : CSTR2SYM("unordered"));
84
+ }
85
+
86
+ static void
87
+ rndr_listitem(struct buf *ob, const struct buf *text, int flags, void *opaque)
88
+ {
89
+ BLOCK_CALLBACK("list_item", 2, buf2str(text),
90
+ (flags & MKD_LIST_ORDERED) ? CSTR2SYM("ordered") : CSTR2SYM("unordered"));
91
+ }
92
+
93
+ static void
94
+ rndr_paragraph(struct buf *ob, const struct buf *text, void *opaque)
95
+ {
96
+ BLOCK_CALLBACK("paragraph", 1, buf2str(text));
97
+ }
98
+
99
+ static void
100
+ rndr_table(struct buf *ob, const struct buf *header, const struct buf *body, void *opaque)
101
+ {
102
+ BLOCK_CALLBACK("table", 2, buf2str(header), buf2str(body));
103
+ }
104
+
105
+ static void
106
+ rndr_tablerow(struct buf *ob, const struct buf *text, void *opaque)
107
+ {
108
+ BLOCK_CALLBACK("table_row", 1, buf2str(text));
109
+ }
110
+
111
+ static void
112
+ rndr_tablecell(struct buf *ob, const struct buf *text, int align, void *opaque)
113
+ {
114
+ VALUE rb_align;
115
+
116
+ switch (align) {
117
+ case MKD_TABLE_ALIGN_L:
118
+ rb_align = CSTR2SYM("left");
119
+ break;
120
+
121
+ case MKD_TABLE_ALIGN_R:
122
+ rb_align = CSTR2SYM("right");
123
+ break;
124
+
125
+ case MKD_TABLE_ALIGN_CENTER:
126
+ rb_align = CSTR2SYM("center");
127
+ break;
128
+
129
+ default:
130
+ rb_align = Qnil;
131
+ break;
132
+ }
133
+
134
+ BLOCK_CALLBACK("table_cell", 2, buf2str(text), rb_align);
135
+ }
136
+
137
+
138
+
139
+
140
+ /***
141
+ * SPAN LEVEL
142
+ */
143
+ static int
144
+ rndr_autolink(struct buf *ob, const struct buf *link, enum mkd_autolink type, void *opaque)
145
+ {
146
+ SPAN_CALLBACK("autolink", 2, buf2str(link),
147
+ type == MKDA_NORMAL ? CSTR2SYM("url") : CSTR2SYM("email"));
148
+ }
149
+
150
+ static int
151
+ rndr_codespan(struct buf *ob, const struct buf *text, void *opaque)
152
+ {
153
+ SPAN_CALLBACK("codespan", 1, buf2str(text));
154
+ }
155
+
156
+ static int
157
+ rndr_double_emphasis(struct buf *ob, const struct buf *text, void *opaque)
158
+ {
159
+ SPAN_CALLBACK("double_emphasis", 1, buf2str(text));
160
+ }
161
+
162
+ static int
163
+ rndr_emphasis(struct buf *ob, const struct buf *text, void *opaque)
164
+ {
165
+ SPAN_CALLBACK("emphasis", 1, buf2str(text));
166
+ }
167
+
168
+ static int
169
+ rndr_image(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *alt, void *opaque)
170
+ {
171
+ SPAN_CALLBACK("image", 3, buf2str(link), buf2str(title), buf2str(alt));
172
+ }
173
+
174
+ static int
175
+ rndr_linebreak(struct buf *ob, void *opaque)
176
+ {
177
+ SPAN_CALLBACK("linebreak", 0);
178
+ }
179
+
180
+ static int
181
+ rndr_link(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *content, void *opaque)
182
+ {
183
+ SPAN_CALLBACK("link", 3, buf2str(link), buf2str(title), buf2str(content));
184
+ }
185
+
186
+ static int
187
+ rndr_raw_html(struct buf *ob, const struct buf *text, void *opaque)
188
+ {
189
+ SPAN_CALLBACK("raw_html", 1, buf2str(text));
190
+ }
191
+
192
+ static int
193
+ rndr_triple_emphasis(struct buf *ob, const struct buf *text, void *opaque)
194
+ {
195
+ SPAN_CALLBACK("triple_emphasis", 1, buf2str(text));
196
+ }
197
+
198
+ static int
199
+ rndr_strikethrough(struct buf *ob, const struct buf *text, void *opaque)
200
+ {
201
+ SPAN_CALLBACK("strikethrough", 1, buf2str(text));
202
+ }
203
+
204
+ static int
205
+ rndr_superscript(struct buf *ob, const struct buf *text, void *opaque)
206
+ {
207
+ SPAN_CALLBACK("superscript", 1, buf2str(text));
208
+ }
209
+
210
+ /**
211
+ * direct writes
212
+ */
213
+ static void
214
+ rndr_entity(struct buf *ob, const struct buf *text, void *opaque)
215
+ {
216
+ BLOCK_CALLBACK("entity", 1, buf2str(text));
217
+ }
218
+
219
+ static void
220
+ rndr_normal_text(struct buf *ob, const struct buf *text, void *opaque)
221
+ {
222
+ BLOCK_CALLBACK("normal_text", 1, buf2str(text));
223
+ }
224
+
225
+ static void
226
+ rndr_doc_header(struct buf *ob, void *opaque)
227
+ {
228
+ BLOCK_CALLBACK("doc_header", 0);
229
+ }
230
+
231
+ static void
232
+ rndr_doc_footer(struct buf *ob, void *opaque)
233
+ {
234
+ BLOCK_CALLBACK("doc_footer", 0);
235
+ }
236
+
237
+ static int
238
+ cb_link_attribute(VALUE key, VALUE val, VALUE payload)
239
+ {
240
+ struct buf *ob = (struct buf *)payload;
241
+ key = rb_obj_as_string(key);
242
+ val = rb_obj_as_string(val);
243
+ bufprintf(ob, " %s=\"%s\"", StringValueCStr(key), StringValueCStr(val));
244
+ return 0;
245
+ }
246
+
247
+ static void
248
+ rndr_link_attributes(struct buf *ob, const struct buf *url, void *opaque)
249
+ {
250
+ struct redcarpet_renderopt *opt = opaque;
251
+ struct rb_redcarpet_rndr *rndr;
252
+
253
+ Data_Get_Struct(opt->self, struct rb_redcarpet_rndr, rndr);
254
+ Check_Type(opt->link_attributes, T_HASH);
255
+ rb_hash_foreach(opt->link_attributes, &cb_link_attribute, (VALUE)ob);
256
+ }
257
+
258
+ static struct sd_callbacks rb_redcarpet_callbacks = {
259
+ rndr_blockcode,
260
+ rndr_blockquote,
261
+ rndr_raw_block,
262
+ rndr_header,
263
+ rndr_hrule,
264
+ rndr_list,
265
+ rndr_listitem,
266
+ rndr_paragraph,
267
+ rndr_table,
268
+ rndr_tablerow,
269
+ rndr_tablecell,
270
+
271
+ rndr_autolink,
272
+ rndr_codespan,
273
+ rndr_double_emphasis,
274
+ rndr_emphasis,
275
+ rndr_image,
276
+ rndr_linebreak,
277
+ rndr_link,
278
+ rndr_raw_html,
279
+ rndr_triple_emphasis,
280
+ rndr_strikethrough,
281
+ rndr_superscript,
282
+
283
+ rndr_entity,
284
+ rndr_normal_text,
285
+
286
+ rndr_doc_header,
287
+ rndr_doc_footer,
288
+ };
289
+
290
+ static const char *rb_redcarpet_method_names[] = {
291
+ "block_code",
292
+ "block_quote",
293
+ "block_html",
294
+ "header",
295
+ "hrule",
296
+ "list",
297
+ "list_item",
298
+ "paragraph",
299
+ "table",
300
+ "table_row",
301
+ "table_cell",
302
+
303
+ "autolink",
304
+ "codespan",
305
+ "double_emphasis",
306
+ "emphasis",
307
+ "image",
308
+ "linebreak",
309
+ "link",
310
+ "raw_html",
311
+ "triple_emphasis",
312
+ "strikethrough",
313
+ "superscript",
314
+
315
+ "entity",
316
+ "normal_text",
317
+
318
+ "doc_header",
319
+ "doc_footer"
320
+ };
321
+
322
+ static const size_t rb_redcarpet_method_count = sizeof(rb_redcarpet_method_names)/sizeof(char *);
323
+
324
+ static void rb_redcarpet_rbase_mark(struct rb_redcarpet_rndr *rndr)
325
+ {
326
+ if (rndr->options.link_attributes)
327
+ rb_gc_mark(rndr->options.link_attributes);
328
+ }
329
+
330
+ static VALUE rb_redcarpet_rbase_alloc(VALUE klass)
331
+ {
332
+ struct rb_redcarpet_rndr *rndr = ALLOC(struct rb_redcarpet_rndr);
333
+ memset(rndr, 0x0, sizeof(struct rb_redcarpet_rndr));
334
+ return Data_Wrap_Struct(klass, rb_redcarpet_rbase_mark, NULL, rndr);
335
+ }
336
+
337
+ static void rb_redcarpet__overload(VALUE self, VALUE base_class)
338
+ {
339
+ struct rb_redcarpet_rndr *rndr;
340
+
341
+ Data_Get_Struct(self, struct rb_redcarpet_rndr, rndr);
342
+ rndr->options.self = self;
343
+ rndr->options.base_class = base_class;
344
+
345
+ if (rb_obj_class(self) == rb_cRenderBase)
346
+ rb_raise(rb_eRuntimeError,
347
+ "The Redcarpet::Render::Base class cannot be instantiated. "
348
+ "Create an inheriting class instead to implement a custom renderer.");
349
+
350
+ if (rb_obj_class(self) != base_class) {
351
+ void **source = (void **)&rb_redcarpet_callbacks;
352
+ void **dest = (void **)&rndr->callbacks;
353
+ size_t i;
354
+
355
+ for (i = 0; i < rb_redcarpet_method_count; ++i) {
356
+ if (rb_respond_to(self, rb_intern(rb_redcarpet_method_names[i])))
357
+ dest[i] = source[i];
358
+ }
359
+ }
360
+ }
361
+
362
+ static VALUE rb_redcarpet_rbase_init(VALUE self)
363
+ {
364
+ rb_redcarpet__overload(self, rb_cRenderBase);
365
+ return Qnil;
366
+ }
367
+
368
+ static VALUE rb_redcarpet_html_init(int argc, VALUE *argv, VALUE self)
369
+ {
370
+ struct rb_redcarpet_rndr *rndr;
371
+ unsigned int render_flags = 0;
372
+ VALUE hash, link_attr = Qnil;
373
+
374
+ Data_Get_Struct(self, struct rb_redcarpet_rndr, rndr);
375
+
376
+ if (rb_scan_args(argc, argv, "01", &hash) == 1) {
377
+ Check_Type(hash, T_HASH);
378
+
379
+ /* escape_html */
380
+ if (rb_hash_aref(hash, CSTR2SYM("escape_html")) == Qtrue)
381
+ render_flags |= HTML_ESCAPE;
382
+
383
+ /* filter_html */
384
+ if (rb_hash_aref(hash, CSTR2SYM("filter_html")) == Qtrue)
385
+ render_flags |= HTML_SKIP_HTML;
386
+
387
+ /* no_image */
388
+ if (rb_hash_aref(hash, CSTR2SYM("no_images")) == Qtrue)
389
+ render_flags |= HTML_SKIP_IMAGES;
390
+
391
+ /* no_links */
392
+ if (rb_hash_aref(hash, CSTR2SYM("no_links")) == Qtrue)
393
+ render_flags |= HTML_SKIP_LINKS;
394
+
395
+ /* filter_style */
396
+ if (rb_hash_aref(hash, CSTR2SYM("no_styles")) == Qtrue)
397
+ render_flags |= HTML_SKIP_STYLE;
398
+
399
+ /* safelink */
400
+ if (rb_hash_aref(hash, CSTR2SYM("safe_links_only")) == Qtrue)
401
+ render_flags |= HTML_SAFELINK;
402
+
403
+ if (rb_hash_aref(hash, CSTR2SYM("with_toc_data")) == Qtrue)
404
+ render_flags |= HTML_TOC;
405
+
406
+ if (rb_hash_aref(hash, CSTR2SYM("hard_wrap")) == Qtrue)
407
+ render_flags |= HTML_HARD_WRAP;
408
+
409
+ if (rb_hash_aref(hash, CSTR2SYM("xhtml")) == Qtrue)
410
+ render_flags |= HTML_USE_XHTML;
411
+
412
+ link_attr = rb_hash_aref(hash, CSTR2SYM("link_attributes"));
413
+ }
414
+
415
+ sdhtml_renderer(&rndr->callbacks, (struct html_renderopt *)&rndr->options.html, render_flags);
416
+ rb_redcarpet__overload(self, rb_cRenderHTML);
417
+
418
+ if (!NIL_P(link_attr)) {
419
+ rndr->options.link_attributes = link_attr;
420
+ rndr->options.html.link_attributes = &rndr_link_attributes;
421
+ }
422
+
423
+ return Qnil;
424
+ }
425
+
426
+ static VALUE rb_redcarpet_htmltoc_init(VALUE self)
427
+ {
428
+ struct rb_redcarpet_rndr *rndr;
429
+ Data_Get_Struct(self, struct rb_redcarpet_rndr, rndr);
430
+
431
+ sdhtml_toc_renderer(&rndr->callbacks, (struct html_renderopt *)&rndr->options.html);
432
+ rb_redcarpet__overload(self, rb_cRenderHTML_TOC);
433
+
434
+ return Qnil;
435
+ }
436
+
437
+ static VALUE rb_redcarpet_smartypants_render(VALUE self, VALUE text)
438
+ {
439
+ VALUE result;
440
+ struct buf *output_buf;
441
+
442
+ Check_Type(text, T_STRING);
443
+
444
+ output_buf = bufnew(128);
445
+
446
+ sdhtml_smartypants(output_buf, RSTRING_PTR(text), RSTRING_LEN(text));
447
+ result = redcarpet_str_new(output_buf->data, output_buf->size, rb_enc_get(text));
448
+
449
+ bufrelease(output_buf);
450
+ return result;
451
+ }
452
+
453
+ void Init_redcarpet_rndr()
454
+ {
455
+ rb_mRender = rb_define_module_under(rb_mRedcarpet, "Render");
456
+
457
+ rb_cRenderBase = rb_define_class_under(rb_mRender, "Base", rb_cObject);
458
+ rb_define_alloc_func(rb_cRenderBase, rb_redcarpet_rbase_alloc);
459
+ rb_define_method(rb_cRenderBase, "initialize", rb_redcarpet_rbase_init, 0);
460
+
461
+ rb_cRenderHTML = rb_define_class_under(rb_mRender, "HTML", rb_cRenderBase);
462
+ rb_define_method(rb_cRenderHTML, "initialize", rb_redcarpet_html_init, -1);
463
+
464
+ rb_cRenderHTML_TOC = rb_define_class_under(rb_mRender, "HTML_TOC", rb_cRenderBase);
465
+ rb_define_method(rb_cRenderHTML_TOC, "initialize", rb_redcarpet_htmltoc_init, 0);
466
+
467
+ rb_mSmartyPants = rb_define_module_under(rb_mRender, "SmartyPants");
468
+ rb_define_method(rb_mSmartyPants, "postprocess", rb_redcarpet_smartypants_render, 1);
469
+ }