redcarpet 2.0.0 → 2.1.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/README.markdown +9 -9
- data/bin/redcarpet +27 -2
- data/ext/redcarpet/buffer.c +14 -20
- data/ext/redcarpet/html.c +42 -17
- data/ext/redcarpet/html.h +1 -0
- data/ext/redcarpet/markdown.c +25 -11
- data/ext/redcarpet/rc_markdown.c +13 -1
- data/ext/redcarpet/rc_render.c +10 -8
- data/ext/redcarpet/redcarpet.h +5 -2
- data/lib/redcarpet/compat.rb +3 -0
- data/lib/redcarpet/render_strip.rb +33 -0
- data/lib/redcarpet.rb +58 -7
- data/redcarpet.gemspec +3 -1
- data/test/redcarpet_test.rb +96 -0
- metadata +7 -5
data/README.markdown
CHANGED
|
@@ -9,12 +9,9 @@ case since version 2 -- it now has its own API, but retains the old name. Yes,
|
|
|
9
9
|
that does mean that Redcarpet 2 is not backwards-compatible with the 1.X
|
|
10
10
|
versions.
|
|
11
11
|
|
|
12
|
-
Redcarpet is powered by the Sundown
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
You might want to find out more about Sundown to see what makes this Ruby
|
|
17
|
-
library so awesome.
|
|
12
|
+
Redcarpet is powered by the [Sundown](https://www.github.com/tanoku/sundown)
|
|
13
|
+
library. You might want to find out more about Sundown to see what makes this
|
|
14
|
+
Ruby library so awesome.
|
|
18
15
|
|
|
19
16
|
This library is written by people
|
|
20
17
|
-------------------------------------------------------
|
|
@@ -66,7 +63,7 @@ settings, and reused between parses.
|
|
|
66
63
|
:tables - parse tables, PHP-Markdown style
|
|
67
64
|
|
|
68
65
|
:fenced_code_blocks - parse fenced code blocks, PHP-Markdown
|
|
69
|
-
style
|
|
66
|
+
style. Blocks delimited with 3 or more `~` or backticks
|
|
70
67
|
will be considered as code, without the need to be
|
|
71
68
|
indented. An optional language name may be added at the
|
|
72
69
|
end of the opening fence for the code block
|
|
@@ -102,7 +99,7 @@ Rendering with the `Markdown` object is done through `Markdown#render`.
|
|
|
102
99
|
Unlike in the RedCloth API, the text to render is passed as an argument
|
|
103
100
|
and not stored inside the `Markdown` instance, to encourage reusability.
|
|
104
101
|
|
|
105
|
-
Markdown
|
|
102
|
+
Markdown#render(text)
|
|
106
103
|
|
|
107
104
|
Render a Markdown document with the attached renderer
|
|
108
105
|
|
|
@@ -253,7 +250,10 @@ The following instance methods may be implemented by the renderer:
|
|
|
253
250
|
# document before or after the rendering process begins
|
|
254
251
|
preprocess(full_document)
|
|
255
252
|
postprocess(full_document)
|
|
256
|
-
|
|
253
|
+
|
|
254
|
+
You can look at
|
|
255
|
+
["How to extend the Redcarpet 2 Markdown library?"](http://dev.af83.com/2012/02/27/howto-extend-the-redcarpet2-markdown-lib.html)
|
|
256
|
+
for some more explanations.
|
|
257
257
|
|
|
258
258
|
Also, now our Pants are much smarter
|
|
259
259
|
------------------------------------
|
data/bin/redcarpet
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
# Usage: redcarpet [<file>...]
|
|
2
|
+
# Usage: redcarpet [--parse-<extension>...] [--render-<extension>...] [--smarty] [<file>...]
|
|
3
3
|
# Convert one or more Markdown files to HTML and write to standard output. With
|
|
4
4
|
# no <file> or when <file> is '-', read Markdown source text from standard input.
|
|
5
|
+
# With <extension>s, perform additional Markdown processing before writing output.
|
|
6
|
+
# With --smarty, use the SmartyHTML renderer
|
|
5
7
|
if ARGV.include?('--help')
|
|
6
8
|
File.read(__FILE__).split("\n").grep(/^# /).each do |line|
|
|
7
9
|
puts line[2..-1]
|
|
@@ -9,5 +11,28 @@ if ARGV.include?('--help')
|
|
|
9
11
|
exit 0
|
|
10
12
|
end
|
|
11
13
|
|
|
14
|
+
root = File.expand_path('../../', __FILE__)
|
|
15
|
+
$:.unshift File.expand_path('lib', root)
|
|
16
|
+
|
|
12
17
|
require 'redcarpet'
|
|
13
|
-
|
|
18
|
+
|
|
19
|
+
render_extensions = {}
|
|
20
|
+
parse_extensions = {}
|
|
21
|
+
renderer = Redcarpet::Render::HTML
|
|
22
|
+
|
|
23
|
+
ARGV.delete_if do |arg|
|
|
24
|
+
if arg =~ /^--render-([\w-]+)$/
|
|
25
|
+
arg = $1.gsub('-', '_')
|
|
26
|
+
render_extensions[arg.to_sym] = true
|
|
27
|
+
elsif arg =~ /^--parse-([\w-]+)$/
|
|
28
|
+
arg = $1.gsub('-', '_')
|
|
29
|
+
parse_extensions[arg.to_sym] = true
|
|
30
|
+
elsif arg == '--smarty'
|
|
31
|
+
renderer = Redcarpet::Render::SmartyHTML
|
|
32
|
+
else
|
|
33
|
+
false
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
render = renderer.new(render_extensions)
|
|
38
|
+
STDOUT.write(Redcarpet::Markdown.new(render, parse_extensions).render(ARGF.read))
|
data/ext/redcarpet/buffer.c
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
#include <stdio.h>
|
|
23
23
|
#include <stdlib.h>
|
|
24
24
|
#include <string.h>
|
|
25
|
+
#include <assert.h>
|
|
25
26
|
|
|
26
27
|
/* MSVC compat */
|
|
27
28
|
#if defined(_MSC_VER)
|
|
@@ -34,6 +35,7 @@ int
|
|
|
34
35
|
bufprefix(const struct buf *buf, const char *prefix)
|
|
35
36
|
{
|
|
36
37
|
size_t i;
|
|
38
|
+
assert(buf && buf->unit);
|
|
37
39
|
|
|
38
40
|
for (i = 0; i < buf->size; ++i) {
|
|
39
41
|
if (prefix[i] == 0)
|
|
@@ -52,7 +54,10 @@ bufgrow(struct buf *buf, size_t neosz)
|
|
|
52
54
|
{
|
|
53
55
|
size_t neoasz;
|
|
54
56
|
void *neodata;
|
|
55
|
-
|
|
57
|
+
|
|
58
|
+
assert(buf && buf->unit);
|
|
59
|
+
|
|
60
|
+
if (neosz > BUFFER_MAX_ALLOC_SIZE)
|
|
56
61
|
return BUF_ENOMEM;
|
|
57
62
|
|
|
58
63
|
if (buf->asize >= neosz)
|
|
@@ -91,8 +96,7 @@ bufnew(size_t unit)
|
|
|
91
96
|
const char *
|
|
92
97
|
bufcstr(struct buf *buf)
|
|
93
98
|
{
|
|
94
|
-
|
|
95
|
-
return NULL;
|
|
99
|
+
assert(buf && buf->unit);
|
|
96
100
|
|
|
97
101
|
if (buf->size < buf->asize && buf->data[buf->size] == 0)
|
|
98
102
|
return (char *)buf->data;
|
|
@@ -110,12 +114,11 @@ void
|
|
|
110
114
|
bufprintf(struct buf *buf, const char *fmt, ...)
|
|
111
115
|
{
|
|
112
116
|
va_list ap;
|
|
113
|
-
if (!buf || !buf->unit)
|
|
114
|
-
return;
|
|
115
|
-
|
|
116
117
|
int n;
|
|
117
118
|
|
|
118
|
-
|
|
119
|
+
assert(buf && buf->unit);
|
|
120
|
+
|
|
121
|
+
if (buf->size >= buf->asize && bufgrow(buf, buf->size + 1) < 0)
|
|
119
122
|
return;
|
|
120
123
|
|
|
121
124
|
va_start(ap, fmt);
|
|
@@ -133,6 +136,7 @@ bufprintf(struct buf *buf, const char *fmt, ...)
|
|
|
133
136
|
if ((size_t)n >= buf->asize - buf->size) {
|
|
134
137
|
if (bufgrow(buf, buf->size + n + 1) < 0)
|
|
135
138
|
return;
|
|
139
|
+
|
|
136
140
|
va_start(ap, fmt);
|
|
137
141
|
n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
|
|
138
142
|
va_end(ap);
|
|
@@ -148,8 +152,7 @@ bufprintf(struct buf *buf, const char *fmt, ...)
|
|
|
148
152
|
void
|
|
149
153
|
bufput(struct buf *buf, const void *data, size_t len)
|
|
150
154
|
{
|
|
151
|
-
|
|
152
|
-
return;
|
|
155
|
+
assert(buf && buf->unit);
|
|
153
156
|
|
|
154
157
|
if (buf->size + len > buf->asize && bufgrow(buf, buf->size + len) < 0)
|
|
155
158
|
return;
|
|
@@ -170,8 +173,7 @@ bufputs(struct buf *buf, const char *str)
|
|
|
170
173
|
void
|
|
171
174
|
bufputc(struct buf *buf, int c)
|
|
172
175
|
{
|
|
173
|
-
|
|
174
|
-
return;
|
|
176
|
+
assert(buf && buf->unit);
|
|
175
177
|
|
|
176
178
|
if (buf->size + 1 > buf->asize && bufgrow(buf, buf->size + 1) < 0)
|
|
177
179
|
return;
|
|
@@ -208,8 +210,7 @@ bufreset(struct buf *buf)
|
|
|
208
210
|
void
|
|
209
211
|
bufslurp(struct buf *buf, size_t len)
|
|
210
212
|
{
|
|
211
|
-
|
|
212
|
-
return;
|
|
213
|
+
assert(buf && buf->unit);
|
|
213
214
|
|
|
214
215
|
if (len >= buf->size) {
|
|
215
216
|
buf->size = 0;
|
|
@@ -220,10 +221,3 @@ bufslurp(struct buf *buf, size_t len)
|
|
|
220
221
|
memmove(buf->data, buf->data + len, buf->size);
|
|
221
222
|
}
|
|
222
223
|
|
|
223
|
-
/* vbufprintf: stdarg variant of formatted printing into a buffer */
|
|
224
|
-
void
|
|
225
|
-
vbufprintf(struct buf *buf, const char *fmt, va_list ap)
|
|
226
|
-
{
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
|
data/ext/redcarpet/html.c
CHANGED
|
@@ -60,6 +60,16 @@ sdhtml_is_tag(const uint8_t *tag_data, size_t tag_size, const char *tagname)
|
|
|
60
60
|
return HTML_TAG_NONE;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
static inline void escape_html(struct buf *ob, const uint8_t *source, size_t length)
|
|
64
|
+
{
|
|
65
|
+
houdini_escape_html0(ob, source, length, 0);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static inline void escape_href(struct buf *ob, const uint8_t *source, size_t length)
|
|
69
|
+
{
|
|
70
|
+
houdini_escape_href(ob, source, length);
|
|
71
|
+
}
|
|
72
|
+
|
|
63
73
|
/********************
|
|
64
74
|
* GENERIC RENDERER *
|
|
65
75
|
********************/
|
|
@@ -79,7 +89,7 @@ rndr_autolink(struct buf *ob, const struct buf *link, enum mkd_autolink type, vo
|
|
|
79
89
|
BUFPUTSL(ob, "<a href=\"");
|
|
80
90
|
if (type == MKDA_EMAIL)
|
|
81
91
|
BUFPUTSL(ob, "mailto:");
|
|
82
|
-
|
|
92
|
+
escape_href(ob, link->data, link->size);
|
|
83
93
|
|
|
84
94
|
if (options->link_attributes) {
|
|
85
95
|
bufputc(ob, '\"');
|
|
@@ -95,9 +105,9 @@ rndr_autolink(struct buf *ob, const struct buf *link, enum mkd_autolink type, vo
|
|
|
95
105
|
* want to print the `mailto:` prefix
|
|
96
106
|
*/
|
|
97
107
|
if (bufprefix(link, "mailto:") == 0) {
|
|
98
|
-
|
|
108
|
+
escape_html(ob, link->data + 7, link->size - 7);
|
|
99
109
|
} else {
|
|
100
|
-
|
|
110
|
+
escape_html(ob, link->data, link->size);
|
|
101
111
|
}
|
|
102
112
|
|
|
103
113
|
BUFPUTSL(ob, "</a>");
|
|
@@ -127,7 +137,7 @@ rndr_blockcode(struct buf *ob, const struct buf *text, const struct buf *lang, v
|
|
|
127
137
|
org++;
|
|
128
138
|
|
|
129
139
|
if (cls) bufputc(ob, ' ');
|
|
130
|
-
|
|
140
|
+
escape_html(ob, lang->data + org, i - org);
|
|
131
141
|
}
|
|
132
142
|
}
|
|
133
143
|
|
|
@@ -136,7 +146,7 @@ rndr_blockcode(struct buf *ob, const struct buf *text, const struct buf *lang, v
|
|
|
136
146
|
BUFPUTSL(ob, "<pre><code>");
|
|
137
147
|
|
|
138
148
|
if (text)
|
|
139
|
-
|
|
149
|
+
escape_html(ob, text->data, text->size);
|
|
140
150
|
|
|
141
151
|
BUFPUTSL(ob, "</code></pre>\n");
|
|
142
152
|
}
|
|
@@ -154,7 +164,7 @@ static int
|
|
|
154
164
|
rndr_codespan(struct buf *ob, const struct buf *text, void *opaque)
|
|
155
165
|
{
|
|
156
166
|
BUFPUTSL(ob, "<code>");
|
|
157
|
-
if (text)
|
|
167
|
+
if (text) escape_html(ob, text->data, text->size);
|
|
158
168
|
BUFPUTSL(ob, "</code>");
|
|
159
169
|
return 1;
|
|
160
170
|
}
|
|
@@ -230,11 +240,11 @@ rndr_link(struct buf *ob, const struct buf *link, const struct buf *title, const
|
|
|
230
240
|
BUFPUTSL(ob, "<a href=\"");
|
|
231
241
|
|
|
232
242
|
if (link && link->size)
|
|
233
|
-
|
|
243
|
+
escape_href(ob, link->data, link->size);
|
|
234
244
|
|
|
235
245
|
if (title && title->size) {
|
|
236
246
|
BUFPUTSL(ob, "\" title=\"");
|
|
237
|
-
|
|
247
|
+
escape_html(ob, title->data, title->size);
|
|
238
248
|
}
|
|
239
249
|
|
|
240
250
|
if (options->link_attributes) {
|
|
@@ -322,9 +332,9 @@ rndr_raw_block(struct buf *ob, const struct buf *text, void *opaque)
|
|
|
322
332
|
size_t org, sz;
|
|
323
333
|
if (!text) return;
|
|
324
334
|
sz = text->size;
|
|
325
|
-
while (sz > 0 && text->data[sz - 1] == '\n') sz
|
|
335
|
+
while (sz > 0 && text->data[sz - 1] == '\n') sz--;
|
|
326
336
|
org = 0;
|
|
327
|
-
while (org < sz && text->data[org] == '\n') org
|
|
337
|
+
while (org < sz && text->data[org] == '\n') org++;
|
|
328
338
|
if (org >= sz) return;
|
|
329
339
|
if (ob->size) bufputc(ob, '\n');
|
|
330
340
|
bufput(ob, text->data + org, sz - org);
|
|
@@ -356,15 +366,15 @@ rndr_image(struct buf *ob, const struct buf *link, const struct buf *title, cons
|
|
|
356
366
|
if (!link || !link->size) return 0;
|
|
357
367
|
|
|
358
368
|
BUFPUTSL(ob, "<img src=\"");
|
|
359
|
-
|
|
369
|
+
escape_href(ob, link->data, link->size);
|
|
360
370
|
BUFPUTSL(ob, "\" alt=\"");
|
|
361
371
|
|
|
362
372
|
if (alt && alt->size)
|
|
363
|
-
|
|
373
|
+
escape_html(ob, alt->data, alt->size);
|
|
364
374
|
|
|
365
375
|
if (title && title->size) {
|
|
366
376
|
BUFPUTSL(ob, "\" title=\"");
|
|
367
|
-
|
|
377
|
+
escape_html(ob, title->data, title->size); }
|
|
368
378
|
|
|
369
379
|
bufputs(ob, USE_XHTML(options) ? "\"/>" : "\">");
|
|
370
380
|
return 1;
|
|
@@ -375,6 +385,13 @@ rndr_raw_html(struct buf *ob, const struct buf *text, void *opaque)
|
|
|
375
385
|
{
|
|
376
386
|
struct html_renderopt *options = opaque;
|
|
377
387
|
|
|
388
|
+
/* HTML_ESCAPE overrides SKIP_HTML, SKIP_STYLE, SKIP_LINKS and SKIP_IMAGES
|
|
389
|
+
* It doens't see if there are any valid tags, just escape all of them. */
|
|
390
|
+
if((options->flags & HTML_ESCAPE) != 0) {
|
|
391
|
+
escape_html(ob, text->data, text->size);
|
|
392
|
+
return 1;
|
|
393
|
+
}
|
|
394
|
+
|
|
378
395
|
if ((options->flags & HTML_SKIP_HTML) != 0)
|
|
379
396
|
return 1;
|
|
380
397
|
|
|
@@ -466,7 +483,7 @@ static void
|
|
|
466
483
|
rndr_normal_text(struct buf *ob, const struct buf *text, void *opaque)
|
|
467
484
|
{
|
|
468
485
|
if (text)
|
|
469
|
-
|
|
486
|
+
escape_html(ob, text->data, text->size);
|
|
470
487
|
}
|
|
471
488
|
|
|
472
489
|
static void
|
|
@@ -492,10 +509,18 @@ toc_header(struct buf *ob, const struct buf *text, int level, void *opaque)
|
|
|
492
509
|
|
|
493
510
|
bufprintf(ob, "<a href=\"#toc_%d\">", options->toc_data.header_count++);
|
|
494
511
|
if (text)
|
|
495
|
-
|
|
512
|
+
escape_html(ob, text->data, text->size);
|
|
496
513
|
BUFPUTSL(ob, "</a>\n");
|
|
497
514
|
}
|
|
498
515
|
|
|
516
|
+
static int
|
|
517
|
+
toc_link(struct buf *ob, const struct buf *link, const struct buf *title, const struct buf *content, void *opaque)
|
|
518
|
+
{
|
|
519
|
+
if (content && content->size)
|
|
520
|
+
bufput(ob, content->data, content->size);
|
|
521
|
+
return 1;
|
|
522
|
+
}
|
|
523
|
+
|
|
499
524
|
static void
|
|
500
525
|
toc_finalize(struct buf *ob, void *opaque)
|
|
501
526
|
{
|
|
@@ -529,7 +554,7 @@ sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *optio
|
|
|
529
554
|
rndr_emphasis,
|
|
530
555
|
NULL,
|
|
531
556
|
NULL,
|
|
532
|
-
|
|
557
|
+
toc_link,
|
|
533
558
|
NULL,
|
|
534
559
|
rndr_triple_emphasis,
|
|
535
560
|
rndr_strikethrough,
|
|
@@ -598,6 +623,6 @@ sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options,
|
|
|
598
623
|
callbacks->autolink = NULL;
|
|
599
624
|
}
|
|
600
625
|
|
|
601
|
-
if (render_flags & HTML_SKIP_HTML)
|
|
626
|
+
if (render_flags & HTML_SKIP_HTML || render_flags & HTML_ESCAPE)
|
|
602
627
|
callbacks->blockhtml = NULL;
|
|
603
628
|
}
|
data/ext/redcarpet/html.h
CHANGED
data/ext/redcarpet/markdown.c
CHANGED
|
@@ -694,6 +694,8 @@ char_escape(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offs
|
|
|
694
694
|
rndr->cb.normal_text(ob, &work, rndr->opaque);
|
|
695
695
|
}
|
|
696
696
|
else bufputc(ob, data[1]);
|
|
697
|
+
} else if (size == 1) {
|
|
698
|
+
bufputc(ob, data[0]);
|
|
697
699
|
}
|
|
698
700
|
|
|
699
701
|
return 2;
|
|
@@ -886,7 +888,8 @@ char_link(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset
|
|
|
886
888
|
/* looking for link end: ' " ) */
|
|
887
889
|
while (i < size) {
|
|
888
890
|
if (data[i] == '\\') i += 2;
|
|
889
|
-
else if (data[i] == ')'
|
|
891
|
+
else if (data[i] == ')') break;
|
|
892
|
+
else if (i >= 1 && _isspace(data[i-1]) && (data[i] == '\'' || data[i] == '"')) break;
|
|
890
893
|
else i++;
|
|
891
894
|
}
|
|
892
895
|
|
|
@@ -1575,7 +1578,7 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t s
|
|
|
1575
1578
|
struct buf *work = 0, *inter = 0;
|
|
1576
1579
|
size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i;
|
|
1577
1580
|
int in_empty = 0, has_inside_empty = 0;
|
|
1578
|
-
|
|
1581
|
+
size_t has_next_uli, has_next_oli;
|
|
1579
1582
|
|
|
1580
1583
|
/* keeping track of the first indentation prefix */
|
|
1581
1584
|
while (orgpre < 3 && orgpre < size && data[orgpre] == ' ')
|
|
@@ -1627,9 +1630,8 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t s
|
|
|
1627
1630
|
|
|
1628
1631
|
/* checking for ul/ol switch */
|
|
1629
1632
|
if (in_empty && (
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
)){
|
|
1633
|
+
((*flags & MKD_LIST_ORDERED) && has_next_uli) ||
|
|
1634
|
+
(!(*flags & MKD_LIST_ORDERED) && has_next_oli))){
|
|
1633
1635
|
*flags |= MKD_LI_END;
|
|
1634
1636
|
break; /* the following item must have same list type */
|
|
1635
1637
|
}
|
|
@@ -1804,7 +1806,7 @@ parse_htmlblock(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
|
|
|
1804
1806
|
i++;
|
|
1805
1807
|
|
|
1806
1808
|
if (i < size)
|
|
1807
|
-
curtag = find_block_tag((char *)data + 1, i - 1);
|
|
1809
|
+
curtag = find_block_tag((char *)data + 1, (int)i - 1);
|
|
1808
1810
|
|
|
1809
1811
|
/* handling of special cases */
|
|
1810
1812
|
if (!curtag) {
|
|
@@ -1968,10 +1970,13 @@ parse_table_header(
|
|
|
1968
1970
|
|
|
1969
1971
|
header_end = i;
|
|
1970
1972
|
|
|
1973
|
+
while (header_end > 0 && _isspace(data[header_end - 1]))
|
|
1974
|
+
header_end--;
|
|
1975
|
+
|
|
1971
1976
|
if (data[0] == '|')
|
|
1972
1977
|
pipes--;
|
|
1973
1978
|
|
|
1974
|
-
if (
|
|
1979
|
+
if (header_end && data[header_end - 1] == '|')
|
|
1975
1980
|
pipes--;
|
|
1976
1981
|
|
|
1977
1982
|
*columns = pipes + 1;
|
|
@@ -2245,8 +2250,8 @@ is_ref(const uint8_t *data, size_t beg, size_t end, size_t *last, struct link_re
|
|
|
2245
2250
|
line_end = title_end;
|
|
2246
2251
|
title_end = i; } }
|
|
2247
2252
|
|
|
2248
|
-
if (!line_end)
|
|
2249
|
-
return 0; /* garbage after the link */
|
|
2253
|
+
if (!line_end || link_end == link_offset)
|
|
2254
|
+
return 0; /* garbage after the link empty link */
|
|
2250
2255
|
|
|
2251
2256
|
/* a valid ref has been found, filling-in return structures */
|
|
2252
2257
|
if (last)
|
|
@@ -2256,6 +2261,8 @@ is_ref(const uint8_t *data, size_t beg, size_t end, size_t *last, struct link_re
|
|
|
2256
2261
|
struct link_ref *ref;
|
|
2257
2262
|
|
|
2258
2263
|
ref = add_link_ref(refs, data + id_offset, id_end - id_offset);
|
|
2264
|
+
if (!ref)
|
|
2265
|
+
return 0;
|
|
2259
2266
|
|
|
2260
2267
|
ref->link = bufnew(link_end - link_offset);
|
|
2261
2268
|
bufput(ref->link, data + link_offset, link_end - link_offset);
|
|
@@ -2361,7 +2368,8 @@ sd_markdown_new(
|
|
|
2361
2368
|
void
|
|
2362
2369
|
sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, struct sd_markdown *md)
|
|
2363
2370
|
{
|
|
2364
|
-
|
|
2371
|
+
#define MARKDOWN_GROW(x) ((x) + ((x) >> 1))
|
|
2372
|
+
static const char UTF8_BOM[] = {0xEF, 0xBB, 0xBF};
|
|
2365
2373
|
|
|
2366
2374
|
struct buf *text;
|
|
2367
2375
|
size_t beg, end;
|
|
@@ -2378,6 +2386,12 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
|
|
|
2378
2386
|
|
|
2379
2387
|
/* first pass: looking for references, copying everything else */
|
|
2380
2388
|
beg = 0;
|
|
2389
|
+
|
|
2390
|
+
/* Skip a possible UTF-8 BOM, even though the Unicode standard
|
|
2391
|
+
* discourages having these in UTF-8 documents */
|
|
2392
|
+
if (doc_size >= 3 && memcmp(document, UTF8_BOM, 3) == 0)
|
|
2393
|
+
beg += 3;
|
|
2394
|
+
|
|
2381
2395
|
while (beg < doc_size) /* iterating over lines */
|
|
2382
2396
|
if (is_ref(document, beg, doc_size, &end, md->refs))
|
|
2383
2397
|
beg = end;
|
|
@@ -2401,7 +2415,7 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
|
|
|
2401
2415
|
}
|
|
2402
2416
|
|
|
2403
2417
|
/* pre-grow the output buffer to minimize allocations */
|
|
2404
|
-
bufgrow(ob, text->size
|
|
2418
|
+
bufgrow(ob, MARKDOWN_GROW(text->size));
|
|
2405
2419
|
|
|
2406
2420
|
/* second pass: actual rendering */
|
|
2407
2421
|
if (md->cb.doc_header)
|
data/ext/redcarpet/rc_markdown.c
CHANGED
|
@@ -24,6 +24,8 @@ static void rb_redcarpet_md_flags(VALUE hash, unsigned int *enabled_extensions_p
|
|
|
24
24
|
{
|
|
25
25
|
unsigned int extensions = 0;
|
|
26
26
|
|
|
27
|
+
Check_Type(hash, T_HASH);
|
|
28
|
+
|
|
27
29
|
/**
|
|
28
30
|
* Markdown extensions -- all disabled by default
|
|
29
31
|
*/
|
|
@@ -102,6 +104,16 @@ static VALUE rb_redcarpet_md_render(VALUE self, VALUE text)
|
|
|
102
104
|
|
|
103
105
|
if (rb_respond_to(rb_rndr, rb_intern("preprocess")))
|
|
104
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
|
|
105
117
|
|
|
106
118
|
/* initialize buffers */
|
|
107
119
|
output_buf = bufnew(128);
|
|
@@ -114,7 +126,7 @@ static VALUE rb_redcarpet_md_render(VALUE self, VALUE text)
|
|
|
114
126
|
markdown);
|
|
115
127
|
|
|
116
128
|
/* build the Ruby string */
|
|
117
|
-
text = redcarpet_str_new(output_buf->data, output_buf->size);
|
|
129
|
+
text = redcarpet_str_new(output_buf->data, output_buf->size, rb_enc_get(text));
|
|
118
130
|
|
|
119
131
|
bufrelease(output_buf);
|
|
120
132
|
|
data/ext/redcarpet/rc_render.c
CHANGED
|
@@ -40,13 +40,11 @@ VALUE rb_cRenderHTML;
|
|
|
40
40
|
VALUE rb_cRenderHTML_TOC;
|
|
41
41
|
VALUE rb_mSmartyPants;
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
buf2str(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
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
|
|
50
48
|
|
|
51
49
|
static void
|
|
52
50
|
rndr_blockcode(struct buf *ob, const struct buf *text, const struct buf *lang, void *opaque)
|
|
@@ -352,6 +350,10 @@ static VALUE rb_redcarpet_html_init(int argc, VALUE *argv, VALUE self)
|
|
|
352
350
|
{
|
|
353
351
|
Check_Type(hash, T_HASH);
|
|
354
352
|
|
|
353
|
+
/* escape_html */
|
|
354
|
+
if (rb_hash_aref(hash, CSTR2SYM("escape_html")) == Qtrue)
|
|
355
|
+
render_flags |= HTML_ESCAPE;
|
|
356
|
+
|
|
355
357
|
/* filter_html */
|
|
356
358
|
if (rb_hash_aref(hash, CSTR2SYM("filter_html")) == Qtrue)
|
|
357
359
|
render_flags |= HTML_SKIP_HTML;
|
|
@@ -409,7 +411,7 @@ static VALUE rb_redcarpet_smartypants_render(VALUE self, VALUE text)
|
|
|
409
411
|
output_buf = bufnew(128);
|
|
410
412
|
|
|
411
413
|
sdhtml_smartypants(output_buf, RSTRING_PTR(text), RSTRING_LEN(text));
|
|
412
|
-
result = redcarpet_str_new(output_buf->data, output_buf->size);
|
|
414
|
+
result = redcarpet_str_new(output_buf->data, output_buf->size, rb_enc_get(text));
|
|
413
415
|
|
|
414
416
|
bufrelease(output_buf);
|
|
415
417
|
return result;
|
data/ext/redcarpet/redcarpet.h
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
#ifdef HAVE_RUBY_ENCODING_H
|
|
9
9
|
# include <ruby/encoding.h>
|
|
10
|
-
# define redcarpet_str_new(data, size) rb_enc_str_new(data, size,
|
|
10
|
+
# define redcarpet_str_new(data, size, enc) rb_enc_str_new(data, size, enc)
|
|
11
11
|
#else
|
|
12
|
-
# define redcarpet_str_new(data, size) rb_str_new(data, size)
|
|
12
|
+
# define redcarpet_str_new(data, size, enc) rb_str_new(data, size)
|
|
13
13
|
#endif
|
|
14
14
|
|
|
15
15
|
#include "markdown.h"
|
|
@@ -23,6 +23,9 @@ struct redcarpet_renderopt {
|
|
|
23
23
|
struct html_renderopt html;
|
|
24
24
|
VALUE self;
|
|
25
25
|
VALUE base_class;
|
|
26
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
|
27
|
+
rb_encoding *active_enc;
|
|
28
|
+
#endif
|
|
26
29
|
};
|
|
27
30
|
|
|
28
31
|
struct rb_redcarpet_rndr {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
|
|
2
|
+
module Redcarpet
|
|
3
|
+
module Render
|
|
4
|
+
# Markdown-stripping renderer. Turns Markdown into plaintext
|
|
5
|
+
# Thanks to @toupeira (Markus Koller)
|
|
6
|
+
class StripDown < Base
|
|
7
|
+
# Methods where the first argument is the text content
|
|
8
|
+
[
|
|
9
|
+
# block-level calls
|
|
10
|
+
:block_code, :block_quote,
|
|
11
|
+
:block_html, :header, :list,
|
|
12
|
+
:list_item, :paragraph,
|
|
13
|
+
|
|
14
|
+
# span-level calls
|
|
15
|
+
:autolink, :codespan, :double_emphasis,
|
|
16
|
+
:emphasis, :raw_html, :triple_emphasis,
|
|
17
|
+
:strikethrough, :superscript,
|
|
18
|
+
|
|
19
|
+
# low level rendering
|
|
20
|
+
:entity, :normal_text
|
|
21
|
+
].each do |method|
|
|
22
|
+
define_method method do |*args|
|
|
23
|
+
args.first
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Other methods where the text content is in another argument
|
|
28
|
+
def link(link, title, content)
|
|
29
|
+
content
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
data/lib/redcarpet.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require 'redcarpet.so'
|
|
2
2
|
|
|
3
3
|
module Redcarpet
|
|
4
|
-
VERSION = '2.
|
|
4
|
+
VERSION = '2.1.1'
|
|
5
5
|
|
|
6
6
|
class Markdown
|
|
7
7
|
attr_reader :renderer
|
|
@@ -54,20 +54,71 @@ module Redcarpet
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
# Compatibility class;
|
|
57
|
-
# Creates
|
|
58
|
-
# API. This instance has no extensions enabled whatsoever,
|
|
59
|
-
# and no accessors to change this. 100% pure, standard
|
|
60
|
-
# Markdown.
|
|
57
|
+
# Creates an instance of Redcarpet with the RedCloth API.
|
|
61
58
|
class RedcarpetCompat
|
|
62
59
|
attr_accessor :text
|
|
63
60
|
|
|
64
|
-
def initialize(text, *
|
|
61
|
+
def initialize(text, *exts)
|
|
62
|
+
exts_hash, render_hash = *parse_extensions_and_renderer_options(exts)
|
|
65
63
|
@text = text
|
|
66
|
-
|
|
64
|
+
renderer = Redcarpet::Render::HTML.new(render_hash)
|
|
65
|
+
@markdown = Redcarpet::Markdown.new(renderer, exts_hash)
|
|
67
66
|
end
|
|
68
67
|
|
|
69
68
|
def to_html(*_dummy)
|
|
70
69
|
@markdown.render(@text)
|
|
71
70
|
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
EXTENSION_MAP = {
|
|
75
|
+
# old name => new name
|
|
76
|
+
:autolink => :autolink,
|
|
77
|
+
:fenced_code => :fenced_code_blocks,
|
|
78
|
+
:filter_html => :filter_html,
|
|
79
|
+
:hard_wrap => :hard_wrap,
|
|
80
|
+
:lax_htmlblock => :lax_html_blocks,
|
|
81
|
+
:no_image => :no_images,
|
|
82
|
+
:no_intraemphasis => :no_intra_emphasis,
|
|
83
|
+
:no_links => :no_links,
|
|
84
|
+
:filter_styles => :no_styles,
|
|
85
|
+
:safelink => :safe_links_only,
|
|
86
|
+
:space_header => :space_after_headers,
|
|
87
|
+
:strikethrough => :strikethrough,
|
|
88
|
+
:tables => :tables,
|
|
89
|
+
:generate_toc => :with_toc_data,
|
|
90
|
+
:xhtml => :xhtml,
|
|
91
|
+
# old names with no new mapping
|
|
92
|
+
:gh_blockcode => nil,
|
|
93
|
+
:no_tables => nil,
|
|
94
|
+
:smart => nil,
|
|
95
|
+
:strict => nil
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
RENDERER_OPTIONS = [:filter_html, :no_images, :no_links, :no_styles,
|
|
99
|
+
:safe_links_only, :with_toc_data, :hard_wrap, :xhtml]
|
|
100
|
+
|
|
101
|
+
def rename_extensions(exts)
|
|
102
|
+
exts.map do |old_name|
|
|
103
|
+
if new_name = EXTENSION_MAP[old_name]
|
|
104
|
+
new_name
|
|
105
|
+
else
|
|
106
|
+
old_name
|
|
107
|
+
end
|
|
108
|
+
end.compact
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Returns two hashes, the extensions and renderer options
|
|
112
|
+
# given the extension list
|
|
113
|
+
def parse_extensions_and_renderer_options(exts)
|
|
114
|
+
exts = rename_extensions(exts)
|
|
115
|
+
exts.partition {|ext| !RENDERER_OPTIONS.include?(ext) }.
|
|
116
|
+
map {|list| list_to_truthy_hash(list) }
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Turns a list of symbols into a hash of <tt>symbol => true</tt>.
|
|
120
|
+
def list_to_truthy_hash(list)
|
|
121
|
+
list.inject({}) {|h, k| h[k] = true; h }
|
|
122
|
+
end
|
|
72
123
|
end
|
|
73
124
|
|
data/redcarpet.gemspec
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
Gem::Specification.new do |s|
|
|
3
3
|
s.name = 'redcarpet'
|
|
4
|
-
s.version = '2.
|
|
4
|
+
s.version = '2.1.1'
|
|
5
5
|
s.summary = "Markdown that smells nice"
|
|
6
6
|
s.description = 'A fast, safe and extensible Markdown to (X)HTML parser'
|
|
7
7
|
s.date = '2011-09-14'
|
|
@@ -34,7 +34,9 @@ Gem::Specification.new do |s|
|
|
|
34
34
|
ext/redcarpet/stack.c
|
|
35
35
|
ext/redcarpet/stack.h
|
|
36
36
|
lib/redcarpet.rb
|
|
37
|
+
lib/redcarpet/compat.rb
|
|
37
38
|
lib/redcarpet/render_man.rb
|
|
39
|
+
lib/redcarpet/render_strip.rb
|
|
38
40
|
redcarpet.gemspec
|
|
39
41
|
sundown
|
|
40
42
|
test/redcarpet_test.rb
|
data/test/redcarpet_test.rb
CHANGED
|
@@ -60,6 +60,8 @@ class HTMLRenderTest < Test::Unit::TestCase
|
|
|
60
60
|
:no_images => Redcarpet::Render::HTML.new(:no_images => true),
|
|
61
61
|
:no_links => Redcarpet::Render::HTML.new(:no_links => true),
|
|
62
62
|
:safe_links => Redcarpet::Render::HTML.new(:safe_links_only => true),
|
|
63
|
+
:escape_html => Redcarpet::Render::HTML.new(:escape_html => true),
|
|
64
|
+
:hard_wrap => Redcarpet::Render::HTML.new(:hard_wrap => true),
|
|
63
65
|
}
|
|
64
66
|
end
|
|
65
67
|
|
|
@@ -67,6 +69,28 @@ class HTMLRenderTest < Test::Unit::TestCase
|
|
|
67
69
|
Redcarpet::Markdown.new(rndr).render(text)
|
|
68
70
|
end
|
|
69
71
|
|
|
72
|
+
# Hint: overrides filter_html, no_images and no_links
|
|
73
|
+
def test_that_escape_html_works
|
|
74
|
+
source = <<EOS
|
|
75
|
+
Through <em>NO</em> <script>DOUBLE NO</script>
|
|
76
|
+
|
|
77
|
+
<script>BAD</script>
|
|
78
|
+
|
|
79
|
+
<img src="/favicon.ico" />
|
|
80
|
+
EOS
|
|
81
|
+
expected = <<EOE
|
|
82
|
+
<p>Through <em>NO</em> <script>DOUBLE NO</script></p>
|
|
83
|
+
|
|
84
|
+
<p><script>BAD</script></p>
|
|
85
|
+
|
|
86
|
+
<p><img src="/favicon.ico" />
|
|
87
|
+
|
|
88
|
+
EOE
|
|
89
|
+
|
|
90
|
+
markdown = render_with(@rndr[:escape_html], source)
|
|
91
|
+
html_equal expected, markdown
|
|
92
|
+
end
|
|
93
|
+
|
|
70
94
|
def test_that_filter_html_works
|
|
71
95
|
markdown = render_with(@rndr[:no_html], 'Through <em>NO</em> <script>DOUBLE NO</script>')
|
|
72
96
|
html_equal "<p>Through NO DOUBLE NO</p>", markdown
|
|
@@ -91,6 +115,18 @@ class HTMLRenderTest < Test::Unit::TestCase
|
|
|
91
115
|
rd = render_with(@rndr[:safe_links], "[IRC](irc://chat.freenode.org/#freenode)")
|
|
92
116
|
html_equal "<p>[IRC](irc://chat.freenode.org/#freenode)</p>\n", rd
|
|
93
117
|
end
|
|
118
|
+
|
|
119
|
+
def test_that_hard_wrap_works
|
|
120
|
+
rd = render_with(@rndr[:hard_wrap], <<EOE)
|
|
121
|
+
Hello world,
|
|
122
|
+
this is just a simple test
|
|
123
|
+
|
|
124
|
+
With hard wraps
|
|
125
|
+
and other *things*.
|
|
126
|
+
EOE
|
|
127
|
+
|
|
128
|
+
assert rd =~ /<br>/
|
|
129
|
+
end
|
|
94
130
|
end
|
|
95
131
|
|
|
96
132
|
class MarkdownTest < Test::Unit::TestCase
|
|
@@ -186,6 +222,18 @@ class MarkdownTest < Test::Unit::TestCase
|
|
|
186
222
|
output = @markdown.render(input)
|
|
187
223
|
assert_equal input.encoding.name, output.encoding.name
|
|
188
224
|
end
|
|
225
|
+
|
|
226
|
+
def test_should_return_string_in_same_encoding_not_in_utf8
|
|
227
|
+
input = "testing".encode('US-ASCII')
|
|
228
|
+
output = @markdown.render(input)
|
|
229
|
+
assert_equal input.encoding.name, output.encoding.name
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def test_should_accept_non_utf8_or_ascii
|
|
233
|
+
input = "testing \xAB\xCD".force_encoding('ASCII-8BIT')
|
|
234
|
+
output = @markdown.render(input)
|
|
235
|
+
assert_equal 'ASCII-8BIT', output.encoding.name
|
|
236
|
+
end
|
|
189
237
|
end
|
|
190
238
|
|
|
191
239
|
def test_that_tags_can_have_dashes_and_underscores
|
|
@@ -293,6 +341,54 @@ class CustomRenderTest < Test::Unit::TestCase
|
|
|
293
341
|
html_equal "<p>This is <em class=\"cool\">just</em> a test</p>",
|
|
294
342
|
md.render("This is *just* a test")
|
|
295
343
|
end
|
|
344
|
+
|
|
345
|
+
class NilPreprocessRenderer < Redcarpet::Render::HTML
|
|
346
|
+
def preprocess(fulldoc)
|
|
347
|
+
nil
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def test_preprocess_returning_nil
|
|
352
|
+
md = Redcarpet::Markdown.new(NilPreprocessRenderer)
|
|
353
|
+
assert_equal(nil,md.render("Anything"))
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
class RedcarpetCompatTest < Test::Unit::TestCase
|
|
359
|
+
def test_simple_compat_api
|
|
360
|
+
html = RedcarpetCompat.new("This is_just_a test").to_html
|
|
361
|
+
html_equal "<p>This is<em>just</em>a test</p>", html
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def test_compat_api_enables_extensions
|
|
365
|
+
html = RedcarpetCompat.new("This is_just_a test", :no_intra_emphasis).to_html
|
|
366
|
+
html_equal "<p>This is_just_a test</p>", html
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def test_compat_api_knows_fenced_code_extension
|
|
370
|
+
text = "```ruby\nx = 'foo'\n```"
|
|
371
|
+
html = RedcarpetCompat.new(text, :fenced_code).to_html
|
|
372
|
+
html_equal "<pre><code class=\"ruby\">x = 'foo'\n</code></pre>", html
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def test_compat_api_ignores_gh_blockcode_extension
|
|
376
|
+
text = "```ruby\nx = 'foo'\n```"
|
|
377
|
+
html = RedcarpetCompat.new(text, :fenced_code, :gh_blockcode).to_html
|
|
378
|
+
html_equal "<pre><code class=\"ruby\">x = 'foo'\n</code></pre>", html
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def test_compat_api_knows_no_intraemphasis_extension
|
|
382
|
+
html = RedcarpetCompat.new("This is_just_a test", :no_intraemphasis).to_html
|
|
383
|
+
html_equal "<p>This is_just_a test</p>", html
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
def test_translate_outdated_extensions
|
|
387
|
+
# these extensions are no longer used
|
|
388
|
+
exts = [:gh_blockcode, :no_tables, :smart, :strict]
|
|
389
|
+
html = RedcarpetCompat.new('"TEST"', *exts).to_html
|
|
390
|
+
html_equal "<p>"TEST"</p>", html
|
|
391
|
+
end
|
|
296
392
|
end
|
|
297
393
|
|
|
298
394
|
# Disabled by default
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: redcarpet
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 9
|
|
5
5
|
prerelease:
|
|
6
6
|
segments:
|
|
7
7
|
- 2
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
version: 2.
|
|
8
|
+
- 1
|
|
9
|
+
- 1
|
|
10
|
+
version: 2.1.1
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- "Natacha Port\xC3\xA9"
|
|
@@ -65,7 +65,9 @@ files:
|
|
|
65
65
|
- ext/redcarpet/stack.c
|
|
66
66
|
- ext/redcarpet/stack.h
|
|
67
67
|
- lib/redcarpet.rb
|
|
68
|
+
- lib/redcarpet/compat.rb
|
|
68
69
|
- lib/redcarpet/render_man.rb
|
|
70
|
+
- lib/redcarpet/render_strip.rb
|
|
69
71
|
- redcarpet.gemspec
|
|
70
72
|
- test/redcarpet_test.rb
|
|
71
73
|
homepage: http://github.com/tanoku/redcarpet
|
|
@@ -97,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
97
99
|
requirements: []
|
|
98
100
|
|
|
99
101
|
rubyforge_project:
|
|
100
|
-
rubygems_version: 1.8.
|
|
102
|
+
rubygems_version: 1.8.15
|
|
101
103
|
signing_key:
|
|
102
104
|
specification_version: 3
|
|
103
105
|
summary: Markdown that smells nice
|