rinku 1.2.2 → 1.3.0
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/Rakefile +0 -18
- data/ext/rinku/autolink.c +13 -13
- data/ext/rinku/autolink.h +7 -4
- data/ext/rinku/buffer.c +123 -218
- data/ext/rinku/buffer.h +49 -112
- data/ext/rinku/houdini.h +28 -0
- data/ext/rinku/houdini_href_e.c +108 -0
- data/ext/rinku/houdini_html_e.c +84 -0
- data/ext/rinku/rinku.c +123 -78
- data/lib/rails_rinku.rb +2 -2
- data/rinku.gemspec +4 -1
- data/test/autolink_test.rb +36 -3
- metadata +8 -7
data/ext/rinku/rinku.c
CHANGED
@@ -34,13 +34,20 @@
|
|
34
34
|
|
35
35
|
static VALUE rb_mRinku;
|
36
36
|
|
37
|
+
typedef enum {
|
38
|
+
HTML_TAG_NONE = 0,
|
39
|
+
HTML_TAG_OPEN,
|
40
|
+
HTML_TAG_CLOSE,
|
41
|
+
} html_tag;
|
42
|
+
|
37
43
|
typedef enum {
|
38
44
|
AUTOLINK_URLS = (1 << 0),
|
39
45
|
AUTOLINK_EMAILS = (1 << 1),
|
46
|
+
AUTOLINK_IN_CODE = (1 << 2),
|
40
47
|
AUTOLINK_ALL = AUTOLINK_URLS|AUTOLINK_EMAILS
|
41
48
|
} autolink_mode;
|
42
49
|
|
43
|
-
typedef size_t (*autolink_parse_cb)(size_t *rewind, struct buf *,
|
50
|
+
typedef size_t (*autolink_parse_cb)(size_t *rewind, struct buf *, uint8_t *, size_t, size_t);
|
44
51
|
|
45
52
|
typedef enum {
|
46
53
|
AUTOLINK_ACTION_NONE = 0,
|
@@ -52,9 +59,9 @@ typedef enum {
|
|
52
59
|
|
53
60
|
static autolink_parse_cb g_callbacks[] = {
|
54
61
|
NULL,
|
55
|
-
|
56
|
-
|
57
|
-
|
62
|
+
sd_autolink__www, /* 1 */
|
63
|
+
sd_autolink__email,/* 2 */
|
64
|
+
sd_autolink__url, /* 3 */
|
58
65
|
};
|
59
66
|
|
60
67
|
static const char *g_hrefs[] = {
|
@@ -65,93 +72,94 @@ static const char *g_hrefs[] = {
|
|
65
72
|
};
|
66
73
|
|
67
74
|
static void
|
68
|
-
|
75
|
+
autolink__html_escape(struct buf *ob, const struct buf *link, void *payload)
|
69
76
|
{
|
70
|
-
|
71
|
-
|
72
|
-
while (i < text->size) {
|
73
|
-
org = i;
|
74
|
-
|
75
|
-
while (i < text->size &&
|
76
|
-
text->data[i] != '<' &&
|
77
|
-
text->data[i] != '>' &&
|
78
|
-
text->data[i] != '&' &&
|
79
|
-
text->data[i] != '"')
|
80
|
-
i++;
|
81
|
-
|
82
|
-
if (i > org)
|
83
|
-
bufput(ob, text->data + org, i - org);
|
84
|
-
|
85
|
-
if (i >= text->size)
|
86
|
-
break;
|
87
|
-
|
88
|
-
switch (text->data[i]) {
|
89
|
-
case '<': BUFPUTSL(ob, "<"); break;
|
90
|
-
case '>': BUFPUTSL(ob, ">"); break;
|
91
|
-
case '&': BUFPUTSL(ob, "&"); break;
|
92
|
-
case '"': BUFPUTSL(ob, """); break;
|
93
|
-
default: bufputc(ob, text->data[i]); break;
|
94
|
-
}
|
95
|
-
|
96
|
-
i++;
|
97
|
-
}
|
77
|
+
houdini_escape_html0(ob, link->data, link->size, 0);
|
98
78
|
}
|
99
79
|
|
100
|
-
|
101
|
-
|
80
|
+
/* From sundown/html/html.c */
|
81
|
+
static int
|
82
|
+
html_is_tag(const uint8_t *tag_data, size_t tag_size, const char *tagname)
|
102
83
|
{
|
103
84
|
size_t i;
|
85
|
+
int closed = 0;
|
104
86
|
|
105
|
-
if (
|
106
|
-
return
|
87
|
+
if (tag_size < 3 || tag_data[0] != '<')
|
88
|
+
return HTML_TAG_NONE;
|
107
89
|
|
108
|
-
i =
|
90
|
+
i = 1;
|
109
91
|
|
110
|
-
|
92
|
+
if (tag_data[i] == '/') {
|
93
|
+
closed = 1;
|
111
94
|
i++;
|
95
|
+
}
|
112
96
|
|
113
|
-
|
114
|
-
|
97
|
+
for (; i < tag_size; ++i, ++tagname) {
|
98
|
+
if (*tagname == 0)
|
99
|
+
break;
|
115
100
|
|
116
|
-
|
101
|
+
if (tag_data[i] != *tagname)
|
102
|
+
return HTML_TAG_NONE;
|
103
|
+
}
|
117
104
|
|
118
|
-
|
119
|
-
|
105
|
+
if (i == tag_size)
|
106
|
+
return HTML_TAG_NONE;
|
120
107
|
|
121
|
-
if (i
|
122
|
-
return
|
108
|
+
if (isspace(tag_data[i]) || tag_data[i] == '>')
|
109
|
+
return closed ? HTML_TAG_CLOSE : HTML_TAG_OPEN;
|
123
110
|
|
124
|
-
return
|
111
|
+
return HTML_TAG_NONE;
|
125
112
|
}
|
126
113
|
|
127
114
|
static size_t
|
128
|
-
autolink__skip_tag(
|
115
|
+
autolink__skip_tag(
|
116
|
+
struct buf *ob,
|
117
|
+
const uint8_t *text,
|
118
|
+
size_t size,
|
119
|
+
const char **skip_tags,
|
120
|
+
size_t skip_tags_count)
|
129
121
|
{
|
130
|
-
size_t i = 0;
|
122
|
+
size_t tag, i = 0;
|
131
123
|
|
132
124
|
while (i < size && text[i] != '>')
|
133
125
|
i++;
|
134
126
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
127
|
+
for (tag = 0; tag < skip_tags_count; ++tag) {
|
128
|
+
if (html_is_tag(text, size, skip_tags[tag]) == HTML_TAG_OPEN)
|
129
|
+
break;
|
130
|
+
}
|
131
|
+
|
132
|
+
if (tag < skip_tags_count) {
|
133
|
+
for (;;) {
|
134
|
+
while (i < size && text[i] != '<')
|
135
|
+
i++;
|
136
|
+
|
137
|
+
if (i == size)
|
140
138
|
break;
|
141
|
-
|
139
|
+
|
140
|
+
if (html_is_tag(text + i, size - i, skip_tags[tag]) == HTML_TAG_CLOSE)
|
141
|
+
break;
|
142
|
+
|
142
143
|
i++;
|
143
144
|
}
|
145
|
+
|
146
|
+
while (i < size && text[i] != '>')
|
147
|
+
i++;
|
144
148
|
}
|
145
149
|
|
146
|
-
|
150
|
+
// bufput(ob, text, i + 1);
|
151
|
+
return i;
|
147
152
|
}
|
148
153
|
|
149
154
|
int
|
150
155
|
rinku_autolink(
|
151
156
|
struct buf *ob,
|
152
|
-
|
157
|
+
const uint8_t *text,
|
158
|
+
size_t size,
|
153
159
|
unsigned int flags,
|
154
160
|
const char *link_attr,
|
161
|
+
const char **skip_tags,
|
162
|
+
size_t skip_tags_count,
|
155
163
|
void (*link_text_cb)(struct buf *ob, const struct buf *link, void *payload),
|
156
164
|
void *payload)
|
157
165
|
{
|
@@ -161,7 +169,7 @@ rinku_autolink(
|
|
161
169
|
void (*link_url_cb)(struct buf *, const struct buf *, void *);
|
162
170
|
int link_count = 0;
|
163
171
|
|
164
|
-
if (!text ||
|
172
|
+
if (!text || size == 0)
|
165
173
|
return;
|
166
174
|
|
167
175
|
memset(active_chars, 0x0, sizeof(active_chars));
|
@@ -178,44 +186,48 @@ rinku_autolink(
|
|
178
186
|
}
|
179
187
|
|
180
188
|
if (link_text_cb == NULL)
|
181
|
-
link_text_cb = &
|
189
|
+
link_text_cb = &autolink__html_escape;
|
182
190
|
|
183
191
|
if (link_attr != NULL) {
|
184
192
|
while (isspace(*link_attr))
|
185
193
|
link_attr++;
|
186
194
|
}
|
187
195
|
|
188
|
-
bufgrow(ob,
|
196
|
+
bufgrow(ob, size);
|
189
197
|
|
190
198
|
i = end = 0;
|
191
199
|
|
192
|
-
while (i <
|
200
|
+
while (i < size) {
|
193
201
|
size_t rewind, link_end;
|
194
202
|
char action;
|
195
203
|
|
196
|
-
while (end <
|
204
|
+
while (end < size && (action = active_chars[text[end]]) == 0)
|
197
205
|
end++;
|
198
206
|
|
199
|
-
if (end ==
|
207
|
+
if (end == size) {
|
200
208
|
if (link_count > 0)
|
201
|
-
bufput(ob, text
|
209
|
+
bufput(ob, text + i, end - i);
|
202
210
|
break;
|
203
211
|
}
|
204
212
|
|
205
213
|
if (action == AUTOLINK_ACTION_SKIP_TAG) {
|
206
|
-
end += autolink__skip_tag(ob,
|
214
|
+
end += autolink__skip_tag(ob,
|
215
|
+
text + end, size - end,
|
216
|
+
skip_tags, skip_tags_count);
|
217
|
+
|
207
218
|
continue;
|
208
219
|
}
|
209
220
|
|
210
221
|
link->size = 0;
|
211
|
-
link_end = g_callbacks[(int)action](
|
222
|
+
link_end = g_callbacks[(int)action](
|
223
|
+
&rewind, link, (uint8_t *)text + end, end, size - end);
|
212
224
|
|
213
225
|
/* print the link */
|
214
226
|
if (link_end > 0) {
|
215
|
-
bufput(ob, text
|
227
|
+
bufput(ob, text + i, end - i - rewind);
|
216
228
|
|
217
229
|
bufputs(ob, g_hrefs[(int)action]);
|
218
|
-
|
230
|
+
houdini_escape_href(ob, link->data, link->size);
|
219
231
|
|
220
232
|
if (link_attr) {
|
221
233
|
BUFPUTSL(ob, "\" ");
|
@@ -258,8 +270,8 @@ autolink_callback(struct buf *link_text, const struct buf *link, void *block)
|
|
258
270
|
* Document-method: auto_link
|
259
271
|
*
|
260
272
|
* call-seq:
|
261
|
-
* auto_link(text, mode=:all, link_attr=nil)
|
262
|
-
* auto_link(text, mode=:all, link_attr=nil) { |link_text| ... }
|
273
|
+
* auto_link(text, mode=:all, link_attr=nil, skip_tags=nil)
|
274
|
+
* auto_link(text, mode=:all, link_attr=nil, skip_tags=nil) { |link_text| ... }
|
263
275
|
*
|
264
276
|
* Parses a block of text looking for "safe" urls or email addresses,
|
265
277
|
* and turns them into HTML links with the given attributes.
|
@@ -277,8 +289,9 @@ autolink_callback(struct buf *link_text, const struct buf *link, void *block)
|
|
277
289
|
* HTML, Rinku is smart enough to skip the links that are already enclosed in <a>
|
278
290
|
* tags.
|
279
291
|
*
|
280
|
-
* +mode+ is a symbol, either :all, :urls or :email_addresses,
|
281
|
-
* kind of links will be auto-linked.
|
292
|
+
* +mode+ is a symbol, either :all, :in_code, :urls or :email_addresses,
|
293
|
+
* which specifies which kind of links will be auto-linked. The :in_code symbol
|
294
|
+
* will autolink e
|
282
295
|
*
|
283
296
|
* +link_attr+ is a string containing the link attributes for each link that
|
284
297
|
* will be generated. These attributes are not sanitized and will be include as-is
|
@@ -289,6 +302,9 @@ autolink_callback(struct buf *link_text, const struct buf *link, void *block)
|
|
289
302
|
*
|
290
303
|
* This string can be autogenerated from a hash using the Rails `tag_options` helper.
|
291
304
|
*
|
305
|
+
* +skip_tags+ is a list of strings with the names of HTML tags that will be skipped
|
306
|
+
* when autolinking. If nil, this defaults to ["a", "pre", "code", "kbd", "script"].
|
307
|
+
*
|
292
308
|
* +block+ The method takes an optional block argument. If a block is passed, it will
|
293
309
|
* be yielded for each found link in the text, and its return value will be used instead
|
294
310
|
* of the name of the link. E.g.
|
@@ -301,13 +317,17 @@ autolink_callback(struct buf *link_text, const struct buf *link, void *block)
|
|
301
317
|
static VALUE
|
302
318
|
rb_rinku_autolink(int argc, VALUE *argv, VALUE self)
|
303
319
|
{
|
304
|
-
|
305
|
-
|
320
|
+
static const char *SKIP_TAGS[] = {"a", "pre", "code", "kbd", "script"};
|
321
|
+
|
322
|
+
VALUE result, rb_text, rb_mode, rb_html, rb_skip, rb_block;
|
323
|
+
struct buf *output_buf;
|
306
324
|
int link_mode, count;
|
307
325
|
const char *link_attr = NULL;
|
326
|
+
const char **skip_tags = NULL;
|
327
|
+
size_t skip_tags_count;
|
308
328
|
ID mode_sym;
|
309
329
|
|
310
|
-
rb_scan_args(argc, argv, "
|
330
|
+
rb_scan_args(argc, argv, "13&", &rb_text, &rb_mode, &rb_html, &rb_skip, &rb_block);
|
311
331
|
|
312
332
|
Check_Type(rb_text, T_STRING);
|
313
333
|
|
@@ -323,8 +343,27 @@ rb_rinku_autolink(int argc, VALUE *argv, VALUE self)
|
|
323
343
|
link_attr = RSTRING_PTR(rb_html);
|
324
344
|
}
|
325
345
|
|
326
|
-
|
327
|
-
|
346
|
+
if (!NIL_P(rb_skip)) {
|
347
|
+
long i;
|
348
|
+
|
349
|
+
Check_Type(rb_skip, T_ARRAY);
|
350
|
+
|
351
|
+
skip_tags_count = RARRAY_LEN(rb_skip);
|
352
|
+
skip_tags = malloc(sizeof(void *) * skip_tags_count);
|
353
|
+
if (!skip_tags)
|
354
|
+
rb_raise(rb_eNoMemError, "Out of memory");
|
355
|
+
|
356
|
+
for (i = 0; i < skip_tags_count; ++i) {
|
357
|
+
VALUE tag = rb_ary_entry(rb_skip, i);
|
358
|
+
Check_Type(tag, T_STRING);
|
359
|
+
|
360
|
+
skip_tags[i] = StringValueCStr(tag);
|
361
|
+
}
|
362
|
+
} else {
|
363
|
+
skip_tags = SKIP_TAGS;
|
364
|
+
skip_tags_count = sizeof(SKIP_TAGS) / sizeof(SKIP_TAGS[0]);
|
365
|
+
}
|
366
|
+
|
328
367
|
output_buf = bufnew(32);
|
329
368
|
|
330
369
|
if (mode_sym == rb_intern("all"))
|
@@ -339,9 +378,12 @@ rb_rinku_autolink(int argc, VALUE *argv, VALUE self)
|
|
339
378
|
|
340
379
|
count = rinku_autolink(
|
341
380
|
output_buf,
|
342
|
-
|
381
|
+
RSTRING_PTR(rb_text),
|
382
|
+
RSTRING_LEN(rb_text),
|
343
383
|
link_mode,
|
344
384
|
link_attr,
|
385
|
+
skip_tags,
|
386
|
+
skip_tags_count,
|
345
387
|
RTEST(rb_block) ? &autolink_callback : NULL,
|
346
388
|
(void*)rb_block);
|
347
389
|
|
@@ -352,6 +394,9 @@ rb_rinku_autolink(int argc, VALUE *argv, VALUE self)
|
|
352
394
|
rb_enc_copy(result, rb_text);
|
353
395
|
}
|
354
396
|
|
397
|
+
if (skip_tags != SKIP_TAGS)
|
398
|
+
free(skip_tags);
|
399
|
+
|
355
400
|
bufrelease(output_buf);
|
356
401
|
return result;
|
357
402
|
}
|
data/lib/rails_rinku.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'rinku'
|
2
2
|
|
3
3
|
module RailsRinku
|
4
|
-
def
|
4
|
+
def rinku_auto_link(text, *args, &block)
|
5
5
|
return '' if text.blank?
|
6
6
|
|
7
7
|
options = args.size == 2 ? {} : args.extract_options!
|
@@ -10,7 +10,6 @@ module RailsRinku
|
|
10
10
|
options[:html] = args[1] || {}
|
11
11
|
end
|
12
12
|
options.reverse_merge!(:link => :all, :html => {})
|
13
|
-
text = sanitize(text) unless options[:sanitize] == false
|
14
13
|
|
15
14
|
Rinku.auto_link(text, options[:link], tag_options(options[:html]), &block)
|
16
15
|
end
|
@@ -18,4 +17,5 @@ end
|
|
18
17
|
|
19
18
|
module ActionView::Helpers::TextHelper
|
20
19
|
include RailsRinku
|
20
|
+
alias_method :auto_link, :rinku_auto_link
|
21
21
|
end
|
data/rinku.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'rinku'
|
3
|
-
s.version = '1.
|
3
|
+
s.version = '1.3.0'
|
4
4
|
s.summary = "Mostly autolinking"
|
5
5
|
s.description = <<-EOF
|
6
6
|
A fast and very smart autolinking library that
|
@@ -20,6 +20,9 @@ Gem::Specification.new do |s|
|
|
20
20
|
ext/rinku/buffer.c
|
21
21
|
ext/rinku/buffer.h
|
22
22
|
ext/rinku/extconf.rb
|
23
|
+
ext/rinku/houdini.h
|
24
|
+
ext/rinku/houdini_href_e.c
|
25
|
+
ext/rinku/houdini_html_e.c
|
23
26
|
lib/rinku.rb
|
24
27
|
lib/rails_rinku.rb
|
25
28
|
rinku.gemspec
|
data/test/autolink_test.rb
CHANGED
@@ -4,13 +4,46 @@ $LOAD_PATH.unshift "#{rootdir}/lib"
|
|
4
4
|
|
5
5
|
require 'test/unit'
|
6
6
|
require 'cgi'
|
7
|
+
require 'uri'
|
7
8
|
require 'rinku'
|
8
9
|
|
9
10
|
class RedcarpetAutolinkTest < Test::Unit::TestCase
|
11
|
+
|
12
|
+
SAFE_CHARS = "{}[]~'"
|
13
|
+
|
10
14
|
def assert_linked(expected, url)
|
11
15
|
assert_equal expected, Rinku.auto_link(url)
|
12
16
|
end
|
13
17
|
|
18
|
+
def test_does_not_segfault
|
19
|
+
assert_linked "< this is just a test", "< this is just a test"
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_skips_tags
|
23
|
+
html = <<-html
|
24
|
+
This is just a test. http://www.pokemon.com
|
25
|
+
<div>
|
26
|
+
More test
|
27
|
+
http://www.amd.com
|
28
|
+
</div>
|
29
|
+
<pre>
|
30
|
+
CODE www.less.es
|
31
|
+
</pre>
|
32
|
+
html
|
33
|
+
|
34
|
+
result = <<-result
|
35
|
+
This is just a test. <a href="http://www.pokemon.com">http://www.pokemon.com</a>
|
36
|
+
<div>
|
37
|
+
More test
|
38
|
+
http://www.amd.com
|
39
|
+
</div>
|
40
|
+
<pre>
|
41
|
+
CODE <a href="http://www.less.es">www.less.es</a>
|
42
|
+
</pre>
|
43
|
+
result
|
44
|
+
assert_equal result, Rinku.auto_link(html, :all, nil, ["div", "a"])
|
45
|
+
end
|
46
|
+
|
14
47
|
def test_auto_link_with_brackets
|
15
48
|
link1_raw = 'http://en.wikipedia.org/wiki/Sprite_(computer_graphics)'
|
16
49
|
link1_result = generate_result(link1_raw)
|
@@ -128,12 +161,12 @@ class RedcarpetAutolinkTest < Test::Unit::TestCase
|
|
128
161
|
http://www.mail-archive.com/rails@lists.rubyonrails.org/
|
129
162
|
http://www.amazon.com/Testing-Equal-Sign-In-Path/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1198861734&sr=8-1
|
130
163
|
http://en.wikipedia.org/wiki/Sprite_(computer_graphics)
|
131
|
-
http://en.wikipedia.org/wiki/Texas_hold
|
164
|
+
http://en.wikipedia.org/wiki/Texas_hold%27em
|
132
165
|
https://www.google.com/doku.php?id=gps:resource:scs:start
|
133
166
|
)
|
134
167
|
|
135
168
|
urls.each do |url|
|
136
|
-
assert_linked %(<a href="#{CGI.escapeHTML url}">#{CGI.escapeHTML url}</a>), url
|
169
|
+
assert_linked %(<a href="#{CGI.escapeHTML URI.escape(url, SAFE_CHARS)}">#{CGI.escapeHTML url}</a>), url
|
137
170
|
end
|
138
171
|
end
|
139
172
|
|
@@ -212,7 +245,7 @@ class RedcarpetAutolinkTest < Test::Unit::TestCase
|
|
212
245
|
|
213
246
|
def generate_result(link_text, href = nil)
|
214
247
|
href ||= link_text
|
215
|
-
%{<a href="#{CGI::escapeHTML href}">#{CGI::escapeHTML link_text}</a>}
|
248
|
+
%{<a href="#{CGI::escapeHTML URI.escape(href, SAFE_CHARS)}">#{CGI::escapeHTML link_text}</a>}
|
216
249
|
end
|
217
250
|
|
218
251
|
end
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 1.
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 1.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- "Vicent Mart\xC3\xAD"
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
19
|
-
default_executable:
|
18
|
+
date: 2011-11-08 00:00:00 Z
|
20
19
|
dependencies: []
|
21
20
|
|
22
21
|
description: " A fast and very smart autolinking library that\n acts as a drop-in replacement for Rails `auto_link`\n"
|
@@ -37,11 +36,13 @@ files:
|
|
37
36
|
- ext/rinku/buffer.c
|
38
37
|
- ext/rinku/buffer.h
|
39
38
|
- ext/rinku/extconf.rb
|
39
|
+
- ext/rinku/houdini.h
|
40
|
+
- ext/rinku/houdini_href_e.c
|
41
|
+
- ext/rinku/houdini_html_e.c
|
40
42
|
- lib/rinku.rb
|
41
43
|
- lib/rails_rinku.rb
|
42
44
|
- rinku.gemspec
|
43
45
|
- test/autolink_test.rb
|
44
|
-
has_rdoc: true
|
45
46
|
homepage: http://github.com/tanoku/rinku
|
46
47
|
licenses: []
|
47
48
|
|
@@ -71,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
72
|
requirements: []
|
72
73
|
|
73
74
|
rubyforge_project:
|
74
|
-
rubygems_version: 1.6
|
75
|
+
rubygems_version: 1.8.6
|
75
76
|
signing_key:
|
76
77
|
specification_version: 3
|
77
78
|
summary: Mostly autolinking
|