redcarpet 1.15.2 → 1.16.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of redcarpet might be problematic. Click here for more details.
- data/Rakefile +3 -4
- data/ext/redcarpet/autolink.c +240 -0
- data/ext/redcarpet/html.c +16 -16
- data/ext/redcarpet/html.h +15 -0
- data/ext/redcarpet/html_autolink.c +174 -0
- data/ext/redcarpet/markdown.c +29 -219
- data/ext/redcarpet/markdown.h +9 -0
- data/ext/redcarpet/redcarpet.c +27 -0
- data/lib/redcarpet.rb +1 -1
- data/redcarpet.gemspec +5 -3
- data/test/{rails_test.rb → autolink_test.rb} +36 -36
- metadata +8 -6
data/Rakefile
CHANGED
@@ -116,10 +116,9 @@ task :gather => 'upskirt/src/markdown.h' do |t|
|
|
116
116
|
files =
|
117
117
|
FileList[
|
118
118
|
'upskirt/src/{markdown,buffer,array}.h',
|
119
|
-
'upskirt/src/{markdown,buffer,array}.c',
|
120
|
-
'upskirt/
|
121
|
-
'upskirt/
|
122
|
-
'upskirt/render/html.h',
|
119
|
+
'upskirt/src/{markdown,buffer,array,autolink}.c',
|
120
|
+
'upskirt/html/{html,html_smartypants,html_autolink}.c',
|
121
|
+
'upskirt/html/html.h',
|
123
122
|
]
|
124
123
|
cp files, 'ext/redcarpet/',
|
125
124
|
:preserve => true,
|
@@ -0,0 +1,240 @@
|
|
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 "markdown.h"
|
18
|
+
#include "buffer.h"
|
19
|
+
|
20
|
+
#include <string.h>
|
21
|
+
#include <stdlib.h>
|
22
|
+
#include <stdio.h>
|
23
|
+
#include <ctype.h>
|
24
|
+
|
25
|
+
int
|
26
|
+
is_safe_link(const char *link, size_t link_len)
|
27
|
+
{
|
28
|
+
static const size_t valid_uris_count = 4;
|
29
|
+
static const char *valid_uris[] = {
|
30
|
+
"http://", "https://", "ftp://", "mailto://"
|
31
|
+
};
|
32
|
+
|
33
|
+
size_t i;
|
34
|
+
|
35
|
+
for (i = 0; i < valid_uris_count; ++i) {
|
36
|
+
size_t len = strlen(valid_uris[i]);
|
37
|
+
|
38
|
+
if (link_len > len &&
|
39
|
+
strncasecmp(link, valid_uris[i], len) == 0 &&
|
40
|
+
isalnum(link[len]))
|
41
|
+
return 1;
|
42
|
+
}
|
43
|
+
|
44
|
+
return 0;
|
45
|
+
}
|
46
|
+
|
47
|
+
static size_t
|
48
|
+
autolink_delim(char *data, size_t link_end, size_t offset, size_t size)
|
49
|
+
{
|
50
|
+
char cclose, copen = 0;
|
51
|
+
|
52
|
+
while (link_end > 0) {
|
53
|
+
if (strchr("?!.,", data[link_end - 1]) != NULL)
|
54
|
+
link_end--;
|
55
|
+
|
56
|
+
else if (data[link_end - 1] == ';') {
|
57
|
+
size_t new_end = link_end - 2;
|
58
|
+
|
59
|
+
while (new_end > 0 && isalpha(data[new_end]))
|
60
|
+
new_end--;
|
61
|
+
|
62
|
+
if (new_end < link_end - 2 && data[new_end] == '&')
|
63
|
+
link_end = new_end;
|
64
|
+
else
|
65
|
+
link_end--;
|
66
|
+
}
|
67
|
+
|
68
|
+
else if (data[link_end - 1] == '>') {
|
69
|
+
while (link_end > 0 && data[link_end] != '<')
|
70
|
+
link_end--;
|
71
|
+
}
|
72
|
+
else break;
|
73
|
+
}
|
74
|
+
|
75
|
+
if (link_end == 0)
|
76
|
+
return 0;
|
77
|
+
|
78
|
+
cclose = data[link_end - 1];
|
79
|
+
|
80
|
+
switch (cclose) {
|
81
|
+
case '"': copen = '"'; break;
|
82
|
+
case '\'': copen = '\''; break;
|
83
|
+
case ')': copen = '('; break;
|
84
|
+
case ']': copen = '['; break;
|
85
|
+
case '}': copen = '{'; break;
|
86
|
+
}
|
87
|
+
|
88
|
+
if (copen != 0) {
|
89
|
+
size_t closing = 0;
|
90
|
+
size_t opening = 0;
|
91
|
+
size_t i = 0;
|
92
|
+
|
93
|
+
/* Try to close the final punctuation sign in this same line;
|
94
|
+
* if we managed to close it outside of the URL, that means that it's
|
95
|
+
* not part of the URL. If it closes inside the URL, that means it
|
96
|
+
* is part of the URL.
|
97
|
+
*
|
98
|
+
* Examples:
|
99
|
+
*
|
100
|
+
* foo http://www.pokemon.com/Pikachu_(Electric) bar
|
101
|
+
* => http://www.pokemon.com/Pikachu_(Electric)
|
102
|
+
*
|
103
|
+
* foo (http://www.pokemon.com/Pikachu_(Electric)) bar
|
104
|
+
* => http://www.pokemon.com/Pikachu_(Electric)
|
105
|
+
*
|
106
|
+
* foo http://www.pokemon.com/Pikachu_(Electric)) bar
|
107
|
+
* => http://www.pokemon.com/Pikachu_(Electric))
|
108
|
+
*
|
109
|
+
* (foo http://www.pokemon.com/Pikachu_(Electric)) bar
|
110
|
+
* => foo http://www.pokemon.com/Pikachu_(Electric)
|
111
|
+
*/
|
112
|
+
|
113
|
+
while (i < link_end) {
|
114
|
+
if (data[i] == copen)
|
115
|
+
opening++;
|
116
|
+
else if (data[i] == cclose)
|
117
|
+
closing++;
|
118
|
+
|
119
|
+
i++;
|
120
|
+
}
|
121
|
+
|
122
|
+
if (closing != opening)
|
123
|
+
link_end--;
|
124
|
+
}
|
125
|
+
|
126
|
+
return link_end;
|
127
|
+
}
|
128
|
+
|
129
|
+
size_t
|
130
|
+
ups_autolink__www(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size)
|
131
|
+
{
|
132
|
+
size_t link_end;
|
133
|
+
int np = 0;
|
134
|
+
|
135
|
+
if (offset > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
|
136
|
+
return 0;
|
137
|
+
|
138
|
+
if (size < 4 || memcmp(data, "www.", STRLEN("www.")) != 0)
|
139
|
+
return 0;
|
140
|
+
|
141
|
+
link_end = 0;
|
142
|
+
while (link_end < size && !isspace(data[link_end])) {
|
143
|
+
if (data[link_end] == '.')
|
144
|
+
np++;
|
145
|
+
|
146
|
+
link_end++;
|
147
|
+
}
|
148
|
+
|
149
|
+
if (np < 2)
|
150
|
+
return 0;
|
151
|
+
|
152
|
+
link_end = autolink_delim(data, link_end, offset, size);
|
153
|
+
|
154
|
+
if (link_end == 0)
|
155
|
+
return 0;
|
156
|
+
|
157
|
+
bufput(link, data, link_end);
|
158
|
+
*rewind_p = 0;
|
159
|
+
|
160
|
+
return (int)link_end;
|
161
|
+
}
|
162
|
+
|
163
|
+
size_t
|
164
|
+
ups_autolink__email(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size)
|
165
|
+
{
|
166
|
+
size_t link_end, rewind;
|
167
|
+
int nb = 0, np = 0;
|
168
|
+
|
169
|
+
for (rewind = 0; rewind < offset; ++rewind) {
|
170
|
+
char c = data[-rewind - 1];
|
171
|
+
|
172
|
+
if (isalnum(c))
|
173
|
+
continue;
|
174
|
+
|
175
|
+
if (strchr(".+-_", c) != NULL)
|
176
|
+
continue;
|
177
|
+
|
178
|
+
break;
|
179
|
+
}
|
180
|
+
|
181
|
+
if (rewind == 0)
|
182
|
+
return 0;
|
183
|
+
|
184
|
+
for (link_end = 0; link_end < size; ++link_end) {
|
185
|
+
char c = data[link_end];
|
186
|
+
|
187
|
+
if (isalnum(c))
|
188
|
+
continue;
|
189
|
+
|
190
|
+
if (c == '@')
|
191
|
+
nb++;
|
192
|
+
else if (c == '.' && link_end < size - 1)
|
193
|
+
np++;
|
194
|
+
else if (c != '-' && c != '_')
|
195
|
+
break;
|
196
|
+
}
|
197
|
+
|
198
|
+
if (link_end < 2 || nb != 1 || np == 0)
|
199
|
+
return 0;
|
200
|
+
|
201
|
+
link_end = autolink_delim(data, link_end, offset, size);
|
202
|
+
|
203
|
+
if (link_end == 0)
|
204
|
+
return 0;
|
205
|
+
|
206
|
+
bufput(link, data - rewind, link_end + rewind);
|
207
|
+
*rewind_p = rewind;
|
208
|
+
|
209
|
+
return link_end;
|
210
|
+
}
|
211
|
+
|
212
|
+
size_t
|
213
|
+
ups_autolink__url(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size)
|
214
|
+
{
|
215
|
+
size_t link_end, rewind = 0;
|
216
|
+
|
217
|
+
if (size < 4 || data[1] != '/' || data[2] != '/')
|
218
|
+
return 0;
|
219
|
+
|
220
|
+
while (rewind < offset && isalpha(data[-rewind - 1]))
|
221
|
+
rewind++;
|
222
|
+
|
223
|
+
if (!is_safe_link(data - rewind, size + rewind))
|
224
|
+
return 0;
|
225
|
+
|
226
|
+
link_end = 0;
|
227
|
+
while (link_end < size && !isspace(data[link_end]))
|
228
|
+
link_end++;
|
229
|
+
|
230
|
+
link_end = autolink_delim(data, link_end, offset, size);
|
231
|
+
|
232
|
+
if (link_end == 0)
|
233
|
+
return 0;
|
234
|
+
|
235
|
+
bufput(link, data - rewind, link_end + rewind);
|
236
|
+
*rewind_p = rewind;
|
237
|
+
|
238
|
+
return link_end;
|
239
|
+
}
|
240
|
+
|
data/ext/redcarpet/html.c
CHANGED
@@ -45,9 +45,9 @@ put_scaped_char(struct buf *ob, char c)
|
|
45
45
|
}
|
46
46
|
}
|
47
47
|
|
48
|
-
/*
|
49
|
-
|
50
|
-
|
48
|
+
/* upshtml_escape • copy the buffer entity-escaping '<', '>', '&' and '"' */
|
49
|
+
void
|
50
|
+
upshtml_escape(struct buf *ob, const char *src, size_t size)
|
51
51
|
{
|
52
52
|
size_t i = 0, org;
|
53
53
|
while (i < size) {
|
@@ -127,9 +127,9 @@ rndr_autolink(struct buf *ob, struct buf *link, enum mkd_autolink type, void *op
|
|
127
127
|
* want to print the `mailto:` prefix
|
128
128
|
*/
|
129
129
|
if (bufprefix(link, "mailto:") == 0) {
|
130
|
-
|
130
|
+
upshtml_escape(ob, link->data + 7, link->size - 7);
|
131
131
|
} else {
|
132
|
-
|
132
|
+
upshtml_escape(ob, link->data, link->size);
|
133
133
|
}
|
134
134
|
|
135
135
|
BUFPUTSL(ob, "</a>");
|
@@ -159,7 +159,7 @@ rndr_blockcode(struct buf *ob, struct buf *text, struct buf *lang, void *opaque)
|
|
159
159
|
org++;
|
160
160
|
|
161
161
|
if (cls) bufputc(ob, ' ');
|
162
|
-
|
162
|
+
upshtml_escape(ob, lang->data + org, i - org);
|
163
163
|
}
|
164
164
|
}
|
165
165
|
|
@@ -168,7 +168,7 @@ rndr_blockcode(struct buf *ob, struct buf *text, struct buf *lang, void *opaque)
|
|
168
168
|
BUFPUTSL(ob, "<pre><code>");
|
169
169
|
|
170
170
|
if (text)
|
171
|
-
|
171
|
+
upshtml_escape(ob, text->data, text->size);
|
172
172
|
|
173
173
|
BUFPUTSL(ob, "</code></pre>\n");
|
174
174
|
}
|
@@ -204,16 +204,16 @@ rndr_blockcode_github(struct buf *ob, struct buf *text, struct buf *lang, void *
|
|
204
204
|
i++;
|
205
205
|
|
206
206
|
if (lang->data[0] == '.')
|
207
|
-
|
207
|
+
upshtml_escape(ob, lang->data + 1, i - 1);
|
208
208
|
else
|
209
|
-
|
209
|
+
upshtml_escape(ob, lang->data, i);
|
210
210
|
|
211
211
|
BUFPUTSL(ob, "\"><code>");
|
212
212
|
} else
|
213
213
|
BUFPUTSL(ob, "<pre><code>");
|
214
214
|
|
215
215
|
if (text)
|
216
|
-
|
216
|
+
upshtml_escape(ob, text->data, text->size);
|
217
217
|
|
218
218
|
BUFPUTSL(ob, "</code></pre>\n");
|
219
219
|
}
|
@@ -230,7 +230,7 @@ static int
|
|
230
230
|
rndr_codespan(struct buf *ob, struct buf *text, void *opaque)
|
231
231
|
{
|
232
232
|
BUFPUTSL(ob, "<code>");
|
233
|
-
if (text)
|
233
|
+
if (text) upshtml_escape(ob, text->data, text->size);
|
234
234
|
BUFPUTSL(ob, "</code>");
|
235
235
|
return 1;
|
236
236
|
}
|
@@ -299,7 +299,7 @@ rndr_link(struct buf *ob, struct buf *link, struct buf *title, struct buf *conte
|
|
299
299
|
if (link && link->size) bufput(ob, link->data, link->size);
|
300
300
|
if (title && title->size) {
|
301
301
|
BUFPUTSL(ob, "\" title=\"");
|
302
|
-
|
302
|
+
upshtml_escape(ob, title->data, title->size); }
|
303
303
|
BUFPUTSL(ob, "\">");
|
304
304
|
if (content && content->size) bufput(ob, content->data, content->size);
|
305
305
|
BUFPUTSL(ob, "</a>");
|
@@ -406,13 +406,13 @@ rndr_image(struct buf *ob, struct buf *link, struct buf *title, struct buf *alt,
|
|
406
406
|
struct html_renderopt *options = opaque;
|
407
407
|
if (!link || !link->size) return 0;
|
408
408
|
BUFPUTSL(ob, "<img src=\"");
|
409
|
-
|
409
|
+
upshtml_escape(ob, link->data, link->size);
|
410
410
|
BUFPUTSL(ob, "\" alt=\"");
|
411
411
|
if (alt && alt->size)
|
412
|
-
|
412
|
+
upshtml_escape(ob, alt->data, alt->size);
|
413
413
|
if (title && title->size) {
|
414
414
|
BUFPUTSL(ob, "\" title=\"");
|
415
|
-
|
415
|
+
upshtml_escape(ob, title->data, title->size); }
|
416
416
|
|
417
417
|
bufputc(ob, '"');
|
418
418
|
bufputs(ob, options->close_tag);
|
@@ -503,7 +503,7 @@ static void
|
|
503
503
|
rndr_normal_text(struct buf *ob, struct buf *text, void *opaque)
|
504
504
|
{
|
505
505
|
if (text)
|
506
|
-
|
506
|
+
upshtml_escape(ob, text->data, text->size);
|
507
507
|
}
|
508
508
|
|
509
509
|
static void
|
data/ext/redcarpet/html.h
CHANGED
@@ -18,6 +18,8 @@
|
|
18
18
|
#define UPSKIRT_HTML_H
|
19
19
|
|
20
20
|
#include "markdown.h"
|
21
|
+
#include "buffer.h"
|
22
|
+
#include <stdlib.h>
|
21
23
|
|
22
24
|
typedef enum {
|
23
25
|
HTML_SKIP_HTML = (1 << 0),
|
@@ -32,6 +34,15 @@ typedef enum {
|
|
32
34
|
HTML_USE_XHTML = (1 << 11),
|
33
35
|
} render_mode;
|
34
36
|
|
37
|
+
typedef enum {
|
38
|
+
AUTOLINK_URLS = (1 << 0),
|
39
|
+
AUTOLINK_EMAILS = (1 << 1),
|
40
|
+
AUTOLINK_ALL = AUTOLINK_URLS|AUTOLINK_EMAILS
|
41
|
+
} autolink_mode;
|
42
|
+
|
43
|
+
void
|
44
|
+
upshtml_escape(struct buf *ob, const char *src, size_t size);
|
45
|
+
|
35
46
|
extern void
|
36
47
|
upshtml_renderer(struct mkd_renderer *renderer, unsigned int render_flags);
|
37
48
|
|
@@ -44,5 +55,9 @@ upshtml_free_renderer(struct mkd_renderer *renderer);
|
|
44
55
|
extern void
|
45
56
|
upshtml_smartypants(struct buf *ob, struct buf *text);
|
46
57
|
|
58
|
+
extern void
|
59
|
+
upshtml_autolink(struct buf *ob, struct buf *text, unsigned int autolink_flags);
|
60
|
+
|
61
|
+
|
47
62
|
#endif
|
48
63
|
|
@@ -0,0 +1,174 @@
|
|
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 "markdown.h"
|
18
|
+
#include "buffer.h"
|
19
|
+
#include "html.h"
|
20
|
+
|
21
|
+
#include <string.h>
|
22
|
+
#include <stdlib.h>
|
23
|
+
#include <stdio.h>
|
24
|
+
#include <ctype.h>
|
25
|
+
|
26
|
+
static inline int
|
27
|
+
is_closing_a(const char *tag, size_t size)
|
28
|
+
{
|
29
|
+
size_t i;
|
30
|
+
|
31
|
+
if (tag[0] != '<' || size < STRLEN("</a>") || tag[1] != '/')
|
32
|
+
return 0;
|
33
|
+
|
34
|
+
i = 2;
|
35
|
+
|
36
|
+
while (i < size && isspace(tag[i]))
|
37
|
+
i++;
|
38
|
+
|
39
|
+
if (i == size || tag[i] != 'a')
|
40
|
+
return 0;
|
41
|
+
|
42
|
+
i++;
|
43
|
+
|
44
|
+
while (i < size && isspace(tag[i]))
|
45
|
+
i++;
|
46
|
+
|
47
|
+
if (i == size || tag[i] != '>')
|
48
|
+
return 0;
|
49
|
+
|
50
|
+
return i;
|
51
|
+
}
|
52
|
+
|
53
|
+
static size_t
|
54
|
+
skip_tags(struct buf *ob, const char *text, size_t size)
|
55
|
+
{
|
56
|
+
size_t i = 0;
|
57
|
+
|
58
|
+
while (i < size && text[i] != '>')
|
59
|
+
i++;
|
60
|
+
|
61
|
+
if (size > 3 && text[1] == 'a' && isspace(text[2])) {
|
62
|
+
while (i < size) {
|
63
|
+
size_t tag_len = is_closing_a(text + i, size - i);
|
64
|
+
if (tag_len) {
|
65
|
+
i += tag_len;
|
66
|
+
break;
|
67
|
+
}
|
68
|
+
i++;
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
bufput(ob, text, i + 1);
|
73
|
+
return i + 1;
|
74
|
+
}
|
75
|
+
|
76
|
+
void
|
77
|
+
upshtml_autolink(struct buf *ob, struct buf *text, unsigned int flags)
|
78
|
+
{
|
79
|
+
size_t i, end;
|
80
|
+
struct buf *link = bufnew(16);
|
81
|
+
const char *active_chars;
|
82
|
+
|
83
|
+
if (!text || text->size == 0)
|
84
|
+
return;
|
85
|
+
|
86
|
+
switch (flags) {
|
87
|
+
case AUTOLINK_EMAILS:
|
88
|
+
active_chars = "<@";
|
89
|
+
break;
|
90
|
+
|
91
|
+
case AUTOLINK_URLS:
|
92
|
+
active_chars = "<w:";
|
93
|
+
|
94
|
+
case AUTOLINK_ALL:
|
95
|
+
active_chars = "<@w:";
|
96
|
+
break;
|
97
|
+
|
98
|
+
default:
|
99
|
+
return;
|
100
|
+
}
|
101
|
+
|
102
|
+
bufgrow(ob, text->size);
|
103
|
+
|
104
|
+
i = end = 0;
|
105
|
+
|
106
|
+
while (i < text->size) {
|
107
|
+
size_t rewind;
|
108
|
+
|
109
|
+
while (end < text->size && strchr(active_chars, text->data[end]) == NULL)
|
110
|
+
end++;
|
111
|
+
|
112
|
+
bufput(ob, text->data + i, end - i);
|
113
|
+
|
114
|
+
if (end >= text->size)
|
115
|
+
break;
|
116
|
+
|
117
|
+
i = end;
|
118
|
+
link->size = 0;
|
119
|
+
|
120
|
+
switch (text->data[i]) {
|
121
|
+
case '@':
|
122
|
+
end = ups_autolink__email(&rewind, link, text->data + i, i, text->size - i);
|
123
|
+
if (end > 0) {
|
124
|
+
ob->size -= rewind;
|
125
|
+
BUFPUTSL(ob, "<a href=\"mailto:");
|
126
|
+
bufput(ob, link->data, link->size);
|
127
|
+
BUFPUTSL(ob, "\">");
|
128
|
+
upshtml_escape(ob, link->data, link->size);
|
129
|
+
BUFPUTSL(ob, "</a>");
|
130
|
+
}
|
131
|
+
break;
|
132
|
+
|
133
|
+
case 'w':
|
134
|
+
end = ups_autolink__www(&rewind, link, text->data + i, i, text->size - i);
|
135
|
+
if (end > 0) {
|
136
|
+
BUFPUTSL(ob, "<a href=\"http://");
|
137
|
+
bufput(ob, link->data, link->size);
|
138
|
+
BUFPUTSL(ob, "\">");
|
139
|
+
upshtml_escape(ob, link->data, link->size);
|
140
|
+
BUFPUTSL(ob, "</a>");
|
141
|
+
}
|
142
|
+
break;
|
143
|
+
|
144
|
+
case ':':
|
145
|
+
end = ups_autolink__url(&rewind, link, text->data + i, i, text->size - i);
|
146
|
+
if (end > 0) {
|
147
|
+
ob->size -= rewind;
|
148
|
+
BUFPUTSL(ob, "<a href=\"");
|
149
|
+
bufput(ob, link->data, link->size);
|
150
|
+
BUFPUTSL(ob, "\">");
|
151
|
+
upshtml_escape(ob, link->data, link->size);
|
152
|
+
BUFPUTSL(ob, "</a>");
|
153
|
+
}
|
154
|
+
break;
|
155
|
+
|
156
|
+
case '<':
|
157
|
+
end = skip_tags(ob, text->data + i, text->size - i);
|
158
|
+
break;
|
159
|
+
|
160
|
+
default:
|
161
|
+
end = 0;
|
162
|
+
break;
|
163
|
+
}
|
164
|
+
|
165
|
+
if (!end)
|
166
|
+
end = i + 1;
|
167
|
+
else {
|
168
|
+
i += end;
|
169
|
+
end = i;
|
170
|
+
}
|
171
|
+
}
|
172
|
+
}
|
173
|
+
|
174
|
+
|
data/ext/redcarpet/markdown.c
CHANGED
@@ -165,28 +165,6 @@ static struct html_tag block_tags[] = {
|
|
165
165
|
/***************************
|
166
166
|
* HELPER FUNCTIONS *
|
167
167
|
***************************/
|
168
|
-
int
|
169
|
-
is_safe_link(const char *link, size_t link_len)
|
170
|
-
{
|
171
|
-
static const size_t valid_uris_count = 4;
|
172
|
-
static const char *valid_uris[] = {
|
173
|
-
"http://", "https://", "ftp://", "mailto://"
|
174
|
-
};
|
175
|
-
|
176
|
-
size_t i;
|
177
|
-
|
178
|
-
for (i = 0; i < valid_uris_count; ++i) {
|
179
|
-
size_t len = strlen(valid_uris[i]);
|
180
|
-
|
181
|
-
if (link_len > len &&
|
182
|
-
strncasecmp(link, valid_uris[i], len) == 0 &&
|
183
|
-
isalnum(link[len]))
|
184
|
-
return 1;
|
185
|
-
}
|
186
|
-
|
187
|
-
return 0;
|
188
|
-
}
|
189
|
-
|
190
168
|
static void
|
191
169
|
unscape_text(struct buf *ob, struct buf *src)
|
192
170
|
{
|
@@ -730,237 +708,69 @@ char_langle_tag(struct buf *ob, struct render *rndr, char *data, size_t offset,
|
|
730
708
|
else return end;
|
731
709
|
}
|
732
710
|
|
733
|
-
static size_t
|
734
|
-
autolink_delim(char *data, size_t link_end, size_t offset, size_t size)
|
735
|
-
{
|
736
|
-
char cclose, copen = 0;
|
737
|
-
|
738
|
-
/* See if the link finishes with a punctuation sign that can be skipped. */
|
739
|
-
switch (data[link_end - 1]) {
|
740
|
-
case '?':
|
741
|
-
case '!':
|
742
|
-
case '.':
|
743
|
-
case ',':
|
744
|
-
link_end--;
|
745
|
-
break;
|
746
|
-
|
747
|
-
case ';':
|
748
|
-
{
|
749
|
-
size_t new_end = link_end - 2;
|
750
|
-
|
751
|
-
while (new_end > 0 && isalpha(data[new_end]))
|
752
|
-
new_end--;
|
753
|
-
|
754
|
-
if (new_end < link_end - 2 && data[new_end] == '&')
|
755
|
-
link_end = new_end;
|
756
|
-
else
|
757
|
-
link_end--;
|
758
|
-
|
759
|
-
break;
|
760
|
-
}
|
761
|
-
|
762
|
-
case '>':
|
763
|
-
while (link_end > 0 && data[link_end] != '<')
|
764
|
-
link_end--;
|
765
|
-
|
766
|
-
if (link_end == 0)
|
767
|
-
return 0;
|
768
|
-
|
769
|
-
break;
|
770
|
-
}
|
771
|
-
|
772
|
-
cclose = data[link_end - 1];
|
773
|
-
|
774
|
-
switch (cclose) {
|
775
|
-
case '"': copen = '"'; break;
|
776
|
-
case '\'': copen = '\''; break;
|
777
|
-
case ')': copen = '('; break;
|
778
|
-
case ']': copen = '['; break;
|
779
|
-
case '}': copen = '{'; break;
|
780
|
-
}
|
781
|
-
|
782
|
-
if (copen != 0) {
|
783
|
-
size_t closing = 0;
|
784
|
-
size_t opening = 0;
|
785
|
-
size_t i = 0;
|
786
|
-
|
787
|
-
/* Try to close the final punctuation sign in this same line;
|
788
|
-
* if we managed to close it outside of the URL, that means that it's
|
789
|
-
* not part of the URL. If it closes inside the URL, that means it
|
790
|
-
* is part of the URL.
|
791
|
-
*
|
792
|
-
* Examples:
|
793
|
-
*
|
794
|
-
* foo http://www.pokemon.com/Pikachu_(Electric) bar
|
795
|
-
* => http://www.pokemon.com/Pikachu_(Electric)
|
796
|
-
*
|
797
|
-
* foo (http://www.pokemon.com/Pikachu_(Electric)) bar
|
798
|
-
* => http://www.pokemon.com/Pikachu_(Electric)
|
799
|
-
*
|
800
|
-
* foo http://www.pokemon.com/Pikachu_(Electric)) bar
|
801
|
-
* => http://www.pokemon.com/Pikachu_(Electric))
|
802
|
-
*
|
803
|
-
* (foo http://www.pokemon.com/Pikachu_(Electric)) bar
|
804
|
-
* => foo http://www.pokemon.com/Pikachu_(Electric)
|
805
|
-
*/
|
806
|
-
|
807
|
-
while (i < link_end) {
|
808
|
-
if (data[i] == copen)
|
809
|
-
opening++;
|
810
|
-
else if (data[i] == cclose)
|
811
|
-
closing++;
|
812
|
-
|
813
|
-
i++;
|
814
|
-
}
|
815
|
-
|
816
|
-
if (closing != opening)
|
817
|
-
link_end--;
|
818
|
-
}
|
819
|
-
|
820
|
-
return link_end;
|
821
|
-
}
|
822
|
-
|
823
|
-
|
824
711
|
static size_t
|
825
712
|
char_autolink_www(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t size)
|
826
713
|
{
|
827
|
-
struct buf
|
828
|
-
size_t
|
829
|
-
int np = 0;
|
830
|
-
|
831
|
-
if (offset > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
|
832
|
-
return 0;
|
833
|
-
|
834
|
-
if (size < 4 || memcmp(data, "www.", STRLEN("www.")) != 0)
|
835
|
-
return 0;
|
836
|
-
|
837
|
-
link_end = 0;
|
838
|
-
while (link_end < size && !isspace(data[link_end])) {
|
839
|
-
if (data[link_end] == '.')
|
840
|
-
np++;
|
841
|
-
|
842
|
-
link_end++;
|
843
|
-
}
|
714
|
+
struct buf *link, *link_url;
|
715
|
+
size_t link_len, rewind;
|
844
716
|
|
845
|
-
if (
|
717
|
+
if (!rndr->make.link)
|
846
718
|
return 0;
|
847
719
|
|
848
|
-
|
720
|
+
link = rndr_newbuf(rndr, BUFFER_SPAN);
|
849
721
|
|
850
|
-
if (
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
work.data = data;
|
855
|
-
|
856
|
-
if (rndr->make.link) {
|
857
|
-
struct buf *u_link = rndr_newbuf(rndr, BUFFER_SPAN);
|
858
|
-
BUFPUTSL(u_link, "http://");
|
859
|
-
unscape_text(u_link, &work);
|
722
|
+
if ((link_len = ups_autolink__www(&rewind, link, data, offset, size)) > 0) {
|
723
|
+
link_url = rndr_newbuf(rndr, BUFFER_SPAN);
|
724
|
+
BUFPUTSL(link_url, "http://");
|
725
|
+
bufput(link_url, link->data, link->size);
|
860
726
|
|
861
|
-
|
727
|
+
ob->size -= rewind;
|
728
|
+
rndr->make.link(ob, link_url, NULL, link, rndr->make.opaque);
|
862
729
|
rndr_popbuf(rndr, BUFFER_SPAN);
|
863
730
|
}
|
864
731
|
|
865
|
-
|
732
|
+
rndr_popbuf(rndr, BUFFER_SPAN);
|
733
|
+
return link_len;
|
866
734
|
}
|
867
735
|
|
868
736
|
static size_t
|
869
737
|
char_autolink_email(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t size)
|
870
738
|
{
|
871
|
-
struct buf
|
872
|
-
size_t
|
873
|
-
int nb = 0, np = 0;
|
874
|
-
|
875
|
-
for (rewind = 0; rewind < offset; ++rewind) {
|
876
|
-
char c = data[-rewind - 1];
|
877
|
-
|
878
|
-
if (isalnum(c))
|
879
|
-
continue;
|
880
|
-
|
881
|
-
if (strchr(".+-_", c) != NULL)
|
882
|
-
continue;
|
883
|
-
|
884
|
-
break;
|
885
|
-
}
|
886
|
-
|
887
|
-
if (rewind == 0)
|
888
|
-
return 0;
|
889
|
-
|
890
|
-
for (link_end = 0; link_end < size; ++link_end) {
|
891
|
-
char c = data[link_end];
|
892
|
-
|
893
|
-
if (isalnum(c))
|
894
|
-
continue;
|
895
|
-
|
896
|
-
if (c == '@')
|
897
|
-
nb++;
|
898
|
-
else if (c == '.' && link_end < size - 1)
|
899
|
-
np++;
|
900
|
-
else if (c != '-' && c != '_')
|
901
|
-
break;
|
902
|
-
}
|
903
|
-
|
904
|
-
if (link_end < 2 || nb != 1 || np == 0)
|
905
|
-
return 0;
|
906
|
-
|
907
|
-
link_end = autolink_delim(data, link_end, offset, size);
|
739
|
+
struct buf *link;
|
740
|
+
size_t link_len, rewind;
|
908
741
|
|
909
|
-
if (
|
742
|
+
if (!rndr->make.autolink)
|
910
743
|
return 0;
|
911
744
|
|
912
|
-
|
913
|
-
work.data = data - rewind;
|
914
|
-
|
915
|
-
if (rndr->make.autolink) {
|
916
|
-
struct buf *u_link = rndr_newbuf(rndr, BUFFER_SPAN);
|
917
|
-
unscape_text(u_link, &work);
|
745
|
+
link = rndr_newbuf(rndr, BUFFER_SPAN);
|
918
746
|
|
747
|
+
if ((link_len = ups_autolink__email(&rewind, link, data, offset, size)) > 0) {
|
919
748
|
ob->size -= rewind;
|
920
|
-
rndr->make.autolink(ob,
|
921
|
-
|
922
|
-
}
|
749
|
+
rndr->make.autolink(ob, link, MKDA_EMAIL, rndr->make.opaque);
|
750
|
+
}
|
923
751
|
|
924
|
-
|
752
|
+
rndr_popbuf(rndr, BUFFER_SPAN);
|
753
|
+
return link_len;
|
925
754
|
}
|
926
755
|
|
927
756
|
static size_t
|
928
757
|
char_autolink_url(struct buf *ob, struct render *rndr, char *data, size_t offset, size_t size)
|
929
758
|
{
|
930
|
-
struct buf
|
931
|
-
size_t
|
932
|
-
|
933
|
-
if (size < 4 || data[1] != '/' || data[2] != '/')
|
934
|
-
return 0;
|
935
|
-
|
936
|
-
while (rewind < offset && isalpha(data[-rewind - 1]))
|
937
|
-
rewind++;
|
938
|
-
|
939
|
-
if (!is_safe_link(data - rewind, size + rewind))
|
940
|
-
return 0;
|
941
|
-
|
942
|
-
link_end = 0;
|
943
|
-
while (link_end < size && !isspace(data[link_end]))
|
944
|
-
link_end++;
|
945
|
-
|
946
|
-
link_end = autolink_delim(data, link_end, offset, size);
|
759
|
+
struct buf *link;
|
760
|
+
size_t link_len, rewind;
|
947
761
|
|
948
|
-
if (
|
762
|
+
if (!rndr->make.autolink)
|
949
763
|
return 0;
|
950
764
|
|
951
|
-
|
952
|
-
work.data = data - rewind;
|
953
|
-
|
954
|
-
if (rndr->make.autolink) {
|
955
|
-
struct buf *u_link = rndr_newbuf(rndr, BUFFER_SPAN);
|
956
|
-
unscape_text(u_link, &work);
|
765
|
+
link = rndr_newbuf(rndr, BUFFER_SPAN);
|
957
766
|
|
767
|
+
if ((link_len = ups_autolink__url(&rewind, link, data, offset, size)) > 0) {
|
958
768
|
ob->size -= rewind;
|
959
|
-
rndr->make.autolink(ob,
|
960
|
-
rndr_popbuf(rndr, BUFFER_SPAN);
|
769
|
+
rndr->make.autolink(ob, link, MKDA_NORMAL, rndr->make.opaque);
|
961
770
|
}
|
962
771
|
|
963
|
-
|
772
|
+
rndr_popbuf(rndr, BUFFER_SPAN);
|
773
|
+
return link_len;
|
964
774
|
}
|
965
775
|
|
966
776
|
/* char_link • '[': parsing a link or an image */
|
data/ext/redcarpet/markdown.h
CHANGED
@@ -105,6 +105,15 @@ struct mkd_renderer {
|
|
105
105
|
int
|
106
106
|
is_safe_link(const char *link, size_t link_len);
|
107
107
|
|
108
|
+
size_t
|
109
|
+
ups_autolink__www(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size);
|
110
|
+
|
111
|
+
size_t
|
112
|
+
ups_autolink__email(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size);
|
113
|
+
|
114
|
+
size_t
|
115
|
+
ups_autolink__url(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size);
|
116
|
+
|
108
117
|
/**********************
|
109
118
|
* EXPORTED FUNCTIONS *
|
110
119
|
**********************/
|
data/ext/redcarpet/redcarpet.c
CHANGED
@@ -79,6 +79,31 @@ static void rb_redcarpet__get_flags(VALUE ruby_obj,
|
|
79
79
|
*render_flags_p = render_flags;
|
80
80
|
}
|
81
81
|
|
82
|
+
static VALUE rb_redcarpet_autolink(VALUE self, VALUE text)
|
83
|
+
{
|
84
|
+
VALUE result;
|
85
|
+
struct buf input_buf, *output_buf;
|
86
|
+
|
87
|
+
memset(&input_buf, 0x0, sizeof(struct buf));
|
88
|
+
input_buf.data = RSTRING_PTR(text);
|
89
|
+
input_buf.size = RSTRING_LEN(text);
|
90
|
+
|
91
|
+
output_buf = bufnew(128);
|
92
|
+
|
93
|
+
upshtml_autolink(output_buf, &input_buf, AUTOLINK_ALL);
|
94
|
+
result = rb_str_new(output_buf->data, output_buf->size);
|
95
|
+
|
96
|
+
bufrelease(output_buf);
|
97
|
+
|
98
|
+
/* force the input encoding */
|
99
|
+
if (rb_respond_to(text, rb_intern("encoding"))) {
|
100
|
+
VALUE encoding = rb_funcall(text, rb_intern("encoding"), 0);
|
101
|
+
rb_funcall(result, rb_intern("force_encoding"), 1, encoding);
|
102
|
+
}
|
103
|
+
|
104
|
+
return result;
|
105
|
+
}
|
106
|
+
|
82
107
|
static VALUE rb_redcarpet__render(VALUE self, RendererType render_type)
|
83
108
|
{
|
84
109
|
VALUE text = rb_funcall(self, rb_intern("text"), 0);
|
@@ -152,5 +177,7 @@ void Init_redcarpet()
|
|
152
177
|
rb_cRedcarpet = rb_define_class("Redcarpet", rb_cObject);
|
153
178
|
rb_define_method(rb_cRedcarpet, "to_html", rb_redcarpet_to_html, -1);
|
154
179
|
rb_define_method(rb_cRedcarpet, "toc_content", rb_redcarpet_toc, -1);
|
180
|
+
|
181
|
+
rb_define_singleton_method(rb_cRedcarpet, "auto_link", rb_redcarpet_autolink, 1);
|
155
182
|
}
|
156
183
|
|
data/lib/redcarpet.rb
CHANGED
data/redcarpet.gemspec
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'redcarpet'
|
3
|
-
s.version = '1.
|
3
|
+
s.version = '1.16.0'
|
4
4
|
s.summary = "Ruby bindings for libupskirt"
|
5
5
|
s.description = 'A fast and safe Markdown to (X)HTML parser'
|
6
|
-
s.date = '2011-06-
|
6
|
+
s.date = '2011-06-08'
|
7
7
|
s.email = 'vicent@github.com'
|
8
8
|
s.homepage = 'http://github.com/tanoku/redcarpet'
|
9
9
|
s.authors = ["Natacha Porté", "Vicent Martí"]
|
@@ -15,11 +15,13 @@ Gem::Specification.new do |s|
|
|
15
15
|
bin/redcarpet
|
16
16
|
ext/redcarpet/array.c
|
17
17
|
ext/redcarpet/array.h
|
18
|
+
ext/redcarpet/autolink.c
|
18
19
|
ext/redcarpet/buffer.c
|
19
20
|
ext/redcarpet/buffer.h
|
20
21
|
ext/redcarpet/extconf.rb
|
21
22
|
ext/redcarpet/html.c
|
22
23
|
ext/redcarpet/html.h
|
24
|
+
ext/redcarpet/html_autolink.c
|
23
25
|
ext/redcarpet/html_smartypants.c
|
24
26
|
ext/redcarpet/markdown.c
|
25
27
|
ext/redcarpet/markdown.h
|
@@ -27,10 +29,10 @@ Gem::Specification.new do |s|
|
|
27
29
|
lib/markdown.rb
|
28
30
|
lib/redcarpet.rb
|
29
31
|
redcarpet.gemspec
|
32
|
+
test/autolink_test.rb
|
30
33
|
test/benchmark.rb
|
31
34
|
test/benchmark.txt
|
32
35
|
test/markdown_test.rb
|
33
|
-
test/rails_test.rb
|
34
36
|
test/redcarpet_test.rb
|
35
37
|
upskirt
|
36
38
|
]
|
@@ -6,17 +6,17 @@ require 'test/unit'
|
|
6
6
|
require 'cgi'
|
7
7
|
require 'redcarpet'
|
8
8
|
|
9
|
-
class
|
9
|
+
class RedcarpetAutolinkTest < Test::Unit::TestCase
|
10
10
|
def assert_linked(expected, url)
|
11
|
-
assert_equal
|
11
|
+
assert_equal expected, Redcarpet.auto_link(url)
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def test_autolink_works
|
15
15
|
url = "http://example.com/"
|
16
16
|
assert_linked "<a href=\"#{url}\">#{url}</a>", url
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
19
|
+
def test_not_autolink_www
|
20
20
|
assert_linked "Awww... man", "Awww... man"
|
21
21
|
end
|
22
22
|
|
@@ -25,8 +25,8 @@ class RedcarpetRailsTest < Test::Unit::TestCase
|
|
25
25
|
assert_linked "<a href=\"#{url}\">#{url}</a>", url
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
29
|
-
url = "http://example.com
|
28
|
+
def test_does_not_include_trailing_gt
|
29
|
+
url = "http://example.com"
|
30
30
|
assert_linked "<<a href=\"#{url}\">#{url}</a>>", "<#{url}>"
|
31
31
|
end
|
32
32
|
|
@@ -60,60 +60,60 @@ class RedcarpetRailsTest < Test::Unit::TestCase
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
def
|
63
|
+
def test_links_like_autolink_rails
|
64
64
|
email_raw = 'david@loudthinking.com'
|
65
65
|
email_result = %{<a href="mailto:#{email_raw}">#{email_raw}</a>}
|
66
66
|
email2_raw = '+david@loudthinking.com'
|
67
67
|
email2_result = %{<a href="mailto:#{email2_raw}">#{email2_raw}</a>}
|
68
68
|
link_raw = 'http://www.rubyonrails.com'
|
69
69
|
link_result = %{<a href="#{link_raw}">#{link_raw}</a>}
|
70
|
-
link_result_with_options = %{<a href="#{link_raw}" target="_blank">#{
|
70
|
+
link_result_with_options = %{<a href="#{link_raw}" target="_blank">#{link_raw}</a>}
|
71
71
|
link2_raw = 'www.rubyonrails.com'
|
72
|
-
link2_result = %{<a href="http://#{link2_raw}">#{
|
72
|
+
link2_result = %{<a href="http://#{link2_raw}">#{link2_raw}</a>}
|
73
73
|
link3_raw = 'http://manuals.ruby-on-rails.com/read/chapter.need_a-period/103#page281'
|
74
|
-
link3_result = %{<a href="#{link3_raw}">#{
|
74
|
+
link3_result = %{<a href="#{link3_raw}">#{link3_raw}</a>}
|
75
75
|
link4_raw = 'http://foo.example.com/controller/action?parm=value&p2=v2#anchor123'
|
76
76
|
link4_result = %{<a href="#{link4_raw}">#{CGI.escapeHTML(link4_raw)}</a>}
|
77
77
|
link5_raw = 'http://foo.example.com:3000/controller/action'
|
78
|
-
link5_result = %{<a href="#{link5_raw}">#{
|
78
|
+
link5_result = %{<a href="#{link5_raw}">#{link5_raw}</a>}
|
79
79
|
link6_raw = 'http://foo.example.com:3000/controller/action+pack'
|
80
|
-
link6_result = %{<a href="#{link6_raw}">#{
|
80
|
+
link6_result = %{<a href="#{link6_raw}">#{link6_raw}</a>}
|
81
81
|
link7_raw = 'http://foo.example.com/controller/action?parm=value&p2=v2#anchor-123'
|
82
82
|
link7_result = %{<a href="#{link7_raw}">#{CGI.escapeHTML(link7_raw)}</a>}
|
83
83
|
link8_raw = 'http://foo.example.com:3000/controller/action.html'
|
84
|
-
link8_result = %{<a href="#{link8_raw}">#{
|
84
|
+
link8_result = %{<a href="#{link8_raw}">#{link8_raw}</a>}
|
85
85
|
link9_raw = 'http://business.timesonline.co.uk/article/0,,9065-2473189,00.html'
|
86
|
-
link9_result = %{<a href="#{link9_raw}">#{
|
86
|
+
link9_result = %{<a href="#{link9_raw}">#{link9_raw}</a>}
|
87
87
|
link10_raw = 'http://www.mail-archive.com/ruby-talk@ruby-lang.org/'
|
88
|
-
link10_result = %{<a href="#{link10_raw}">#{
|
88
|
+
link10_result = %{<a href="#{link10_raw}">#{link10_raw}</a>}
|
89
89
|
|
90
90
|
assert_linked %(Go to #{link_result} and say hello to #{email_result}), "Go to #{link_raw} and say hello to #{email_raw}"
|
91
|
-
assert_linked %(Link #{link_result}), "Link #{link_raw}"
|
92
|
-
assert_linked %(
|
91
|
+
assert_linked %(<p>Link #{link_result}</p>), "<p>Link #{link_raw}</p>"
|
92
|
+
assert_linked %(<p>#{link_result} Link</p>), "<p>#{link_raw} Link</p>"
|
93
93
|
assert_linked %(Go to #{link_result}.), %(Go to #{link_raw}.)
|
94
|
-
assert_linked %(Go to #{link_result}, then say hello to #{email_result}
|
95
|
-
assert_linked %(Link #{link2_result}), "Link #{link2_raw}"
|
96
|
-
assert_linked %(
|
94
|
+
assert_linked %(<p>Go to #{link_result}, then say hello to #{email_result}.</p>), %(<p>Go to #{link_raw}, then say hello to #{email_raw}.</p>)
|
95
|
+
assert_linked %(<p>Link #{link2_result}</p>), "<p>Link #{link2_raw}</p>"
|
96
|
+
assert_linked %(<p>#{link2_result} Link</p>), "<p>#{link2_raw} Link</p>"
|
97
97
|
assert_linked %(Go to #{link2_result}.), %(Go to #{link2_raw}.)
|
98
|
-
assert_linked %(Say hello to #{email_result}, then go to #{link2_result}
|
99
|
-
assert_linked %(Link #{link3_result}), "Link #{link3_raw}"
|
100
|
-
assert_linked %(
|
98
|
+
# assert_linked %(<p>Say hello to #{email_result}, then go to #{link2_result},</p>), %(<p>Say hello to #{email_raw}, then go to #{link2_raw},</p>)
|
99
|
+
assert_linked %(<p>Link #{link3_result}</p>), "<p>Link #{link3_raw}</p>"
|
100
|
+
assert_linked %(<p>#{link3_result} Link</p>), "<p>#{link3_raw} Link</p>"
|
101
101
|
assert_linked %(Go to #{link3_result}.), %(Go to #{link3_raw}.)
|
102
|
-
assert_linked %(Go to #{link3_result}. seriously, #{link3_result}? i think I'll say hello to #{email_result}. instead
|
103
|
-
assert_linked %(Link #{link4_result}), "Link #{link4_raw}"
|
104
|
-
assert_linked %(
|
105
|
-
assert_linked %(
|
106
|
-
assert_linked %(
|
107
|
-
assert_linked %(
|
108
|
-
assert_linked %(Link #{link8_result}), "Link #{link8_raw}"
|
109
|
-
assert_linked %(
|
102
|
+
assert_linked %(<p>Go to #{link3_result}. seriously, #{link3_result}? i think I'll say hello to #{email_result}. instead.</p>), %(<p>Go to #{link3_raw}. seriously, #{link3_raw}? i think I'll say hello to #{email_raw}. instead.</p>)
|
103
|
+
assert_linked %(<p>Link #{link4_result}</p>), "<p>Link #{link4_raw}</p>"
|
104
|
+
assert_linked %(<p>#{link4_result} Link</p>), "<p>#{link4_raw} Link</p>"
|
105
|
+
assert_linked %(<p>#{link5_result} Link</p>), "<p>#{link5_raw} Link</p>"
|
106
|
+
assert_linked %(<p>#{link6_result} Link</p>), "<p>#{link6_raw} Link</p>"
|
107
|
+
assert_linked %(<p>#{link7_result} Link</p>), "<p>#{link7_raw} Link</p>"
|
108
|
+
assert_linked %(<p>Link #{link8_result}</p>), "<p>Link #{link8_raw}</p>"
|
109
|
+
assert_linked %(<p>#{link8_result} Link</p>), "<p>#{link8_raw} Link</p>"
|
110
110
|
assert_linked %(Go to #{link8_result}.), %(Go to #{link8_raw}.)
|
111
|
-
assert_linked %(Go to #{link8_result}. seriously, #{link8_result}? i think I'll say hello to #{email_result}. instead
|
112
|
-
assert_linked %(Link #{link9_result}), "Link #{link9_raw}"
|
113
|
-
|
111
|
+
assert_linked %(<p>Go to #{link8_result}. seriously, #{link8_result}? i think I'll say hello to #{email_result}. instead.</p>), %(<p>Go to #{link8_raw}. seriously, #{link8_raw}? i think I'll say hello to #{email_raw}. instead.</p>)
|
112
|
+
assert_linked %(<p>Link #{link9_result}</p>), "<p>Link #{link9_raw}</p>"
|
113
|
+
assert_linked %(<p>#{link9_result} Link</p>), "<p>#{link9_raw} Link</p>"
|
114
114
|
assert_linked %(Go to #{link9_result}.), %(Go to #{link9_raw}.)
|
115
|
-
|
116
|
-
|
115
|
+
assert_linked %(<p>Go to #{link9_result}. seriously, #{link9_result}? i think I'll say hello to #{email_result}. instead.</p>), %(<p>Go to #{link9_raw}. seriously, #{link9_raw}? i think I'll say hello to #{email_raw}. instead.</p>)
|
116
|
+
assert_linked %(<p>#{link10_result} Link</p>), "<p>#{link10_raw} Link</p>"
|
117
117
|
assert_linked email2_result, email2_raw
|
118
118
|
assert_linked "#{link_result} #{link_result} #{link_result}", "#{link_raw} #{link_raw} #{link_raw}"
|
119
119
|
assert_linked '<a href="http://www.rubyonrails.com">Ruby On Rails</a>', '<a href="http://www.rubyonrails.com">Ruby On Rails</a>'
|
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: 87
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 1.
|
8
|
+
- 16
|
9
|
+
- 0
|
10
|
+
version: 1.16.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- "Natacha Port\xC3\xA9"
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-06-
|
19
|
+
date: 2011-06-08 00:00:00 +02:00
|
20
20
|
default_executable:
|
21
21
|
dependencies: []
|
22
22
|
|
@@ -35,11 +35,13 @@ files:
|
|
35
35
|
- bin/redcarpet
|
36
36
|
- ext/redcarpet/array.c
|
37
37
|
- ext/redcarpet/array.h
|
38
|
+
- ext/redcarpet/autolink.c
|
38
39
|
- ext/redcarpet/buffer.c
|
39
40
|
- ext/redcarpet/buffer.h
|
40
41
|
- ext/redcarpet/extconf.rb
|
41
42
|
- ext/redcarpet/html.c
|
42
43
|
- ext/redcarpet/html.h
|
44
|
+
- ext/redcarpet/html_autolink.c
|
43
45
|
- ext/redcarpet/html_smartypants.c
|
44
46
|
- ext/redcarpet/markdown.c
|
45
47
|
- ext/redcarpet/markdown.h
|
@@ -47,10 +49,10 @@ files:
|
|
47
49
|
- lib/markdown.rb
|
48
50
|
- lib/redcarpet.rb
|
49
51
|
- redcarpet.gemspec
|
52
|
+
- test/autolink_test.rb
|
50
53
|
- test/benchmark.rb
|
51
54
|
- test/benchmark.txt
|
52
55
|
- test/markdown_test.rb
|
53
|
-
- test/rails_test.rb
|
54
56
|
- test/redcarpet_test.rb
|
55
57
|
has_rdoc: true
|
56
58
|
homepage: http://github.com/tanoku/redcarpet
|