rinku 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -56,8 +56,7 @@ task :gather => 'upskirt/src/markdown.h' do |t|
56
56
  files =
57
57
  FileList[
58
58
  'upskirt/src/{buffer,autolink}.h',
59
- 'upskirt/src/{buffer,autolink}.c',
60
- 'upskirt/html/html_autolink.c'
59
+ 'upskirt/src/{buffer,autolink}.c'
61
60
  ]
62
61
  cp files, 'ext/rinku/',
63
62
  :preserve => true,
data/ext/rinku/autolink.h CHANGED
@@ -19,15 +19,6 @@
19
19
 
20
20
  #include "buffer.h"
21
21
 
22
- typedef enum {
23
- AUTOLINK_URLS = (1 << 0),
24
- AUTOLINK_EMAILS = (1 << 1),
25
- AUTOLINK_ALL = AUTOLINK_URLS|AUTOLINK_EMAILS,
26
- AUTOLINK_SANITIZE_NAMES = (1 << 2),
27
- AUTOLINK_SANITIZE_URLS = (1 << 3),
28
- AUTOLINK_SANITIZE = AUTOLINK_SANITIZE_NAMES|AUTOLINK_SANITIZE_URLS,
29
- } autolink_mode;
30
-
31
22
  extern size_t
32
23
  ups_autolink__www(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size);
33
24
 
data/ext/rinku/rinku.c CHANGED
@@ -27,17 +27,223 @@
27
27
  #include "autolink.h"
28
28
  #include "buffer.h"
29
29
 
30
- static VALUE rb_cRinku;
30
+ #include <string.h>
31
+ #include <stdlib.h>
32
+ #include <stdio.h>
33
+ #include <ctype.h>
34
+
35
+ static VALUE rb_mRinku;
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
+ typedef size_t (*autolink_parse_cb)(size_t *rewind, struct buf *, char *, size_t, size_t);
44
+
45
+ typedef enum {
46
+ AUTOLINK_ACTION_NONE = 0,
47
+ AUTOLINK_ACTION_WWW,
48
+ AUTOLINK_ACTION_EMAIL,
49
+ AUTOLINK_ACTION_URL,
50
+ AUTOLINK_ACTION_SKIP_TAG
51
+ } autolink_action;
52
+
53
+ static autolink_parse_cb g_callbacks[] = {
54
+ NULL,
55
+ ups_autolink__www, /* 1 */
56
+ ups_autolink__email,/* 2 */
57
+ ups_autolink__url, /* 3 */
58
+ };
59
+
60
+ static const char *g_hrefs[] = {
61
+ NULL,
62
+ "<a href=\"http://",
63
+ "<a href=\"mailto:",
64
+ "<a href=\"",
65
+ };
66
+
67
+ static void
68
+ autolink_escape_cb(struct buf *ob, const struct buf *text, void *unused)
69
+ {
70
+ size_t i = 0, org;
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, "&lt;"); break;
90
+ case '>': BUFPUTSL(ob, "&gt;"); break;
91
+ case '&': BUFPUTSL(ob, "&amp;"); break;
92
+ case '"': BUFPUTSL(ob, "&quot;"); break;
93
+ default: bufputc(ob, text->data[i]); break;
94
+ }
95
+
96
+ i++;
97
+ }
98
+ }
99
+
100
+ static inline int
101
+ is_closing_a(const char *tag, size_t size)
102
+ {
103
+ size_t i;
104
+
105
+ if (tag[0] != '<' || size < STRLEN("</a>") || tag[1] != '/')
106
+ return 0;
107
+
108
+ i = 2;
109
+
110
+ while (i < size && isspace(tag[i]))
111
+ i++;
112
+
113
+ if (i == size || tag[i] != 'a')
114
+ return 0;
115
+
116
+ i++;
117
+
118
+ while (i < size && isspace(tag[i]))
119
+ i++;
120
+
121
+ if (i == size || tag[i] != '>')
122
+ return 0;
123
+
124
+ return i;
125
+ }
126
+
127
+ static size_t
128
+ autolink__skip_tag(struct buf *ob, char *text, size_t size)
129
+ {
130
+ size_t i = 0;
131
+
132
+ while (i < size && text[i] != '>')
133
+ i++;
134
+
135
+ if (size > 3 && text[1] == 'a' && isspace(text[2])) {
136
+ while (i < size) {
137
+ size_t tag_len = is_closing_a(text + i, size - i);
138
+ if (tag_len) {
139
+ i += tag_len;
140
+ break;
141
+ }
142
+ i++;
143
+ }
144
+ }
31
145
 
32
- extern void
33
- upshtml_autolink(
146
+ return i + 1;
147
+ }
148
+
149
+ int
150
+ rinku_autolink(
34
151
  struct buf *ob,
35
152
  struct buf *text,
36
153
  unsigned int flags,
37
154
  const char *link_attr,
38
155
  void (*link_text_cb)(struct buf *ob, const struct buf *link, void *payload),
39
- void *payload);
156
+ void *payload)
157
+ {
158
+ size_t i, end;
159
+ struct buf *link = bufnew(16);
160
+ char active_chars[256];
161
+ void (*link_url_cb)(struct buf *, const struct buf *, void *);
162
+ int link_count = 0;
163
+
164
+ if (!text || text->size == 0)
165
+ return;
166
+
167
+ memset(active_chars, 0x0, sizeof(active_chars));
168
+
169
+ active_chars['<'] = AUTOLINK_ACTION_SKIP_TAG;
170
+
171
+ if (flags & AUTOLINK_EMAILS)
172
+ active_chars['@'] = AUTOLINK_ACTION_EMAIL;
173
+
174
+ if (flags & AUTOLINK_URLS) {
175
+ active_chars['w'] = AUTOLINK_ACTION_WWW;
176
+ active_chars['W'] = AUTOLINK_ACTION_WWW;
177
+ active_chars[':'] = AUTOLINK_ACTION_URL;
178
+ }
179
+
180
+ if (link_text_cb == NULL)
181
+ link_text_cb = &autolink_escape_cb;
182
+
183
+ if (link_attr != NULL) {
184
+ while (isspace(*link_attr))
185
+ link_attr++;
186
+ }
187
+
188
+ bufgrow(ob, text->size);
189
+
190
+ i = end = 0;
191
+
192
+ while (i < text->size) {
193
+ size_t rewind, link_end;
194
+ char action;
195
+
196
+ while (end < text->size && (action = active_chars[(int)text->data[end]]) == 0)
197
+ end++;
198
+
199
+ if (end == text->size) {
200
+ if (link_count > 0)
201
+ bufput(ob, text->data + i, end - i);
202
+ break;
203
+ }
40
204
 
205
+ if (action == AUTOLINK_ACTION_SKIP_TAG) {
206
+ end += autolink__skip_tag(ob, text->data + end, text->size - end);
207
+ continue;
208
+ }
209
+
210
+ link->size = 0;
211
+ link_end = g_callbacks[(int)action](&rewind, link, text->data + end, end, text->size - end);
212
+
213
+ /* print the link */
214
+ if (link_end > 0) {
215
+ bufput(ob, text->data + i, end - i - rewind);
216
+
217
+ bufputs(ob, g_hrefs[(int)action]);
218
+ autolink_escape_cb(ob, link, NULL);
219
+
220
+ if (link_attr) {
221
+ BUFPUTSL(ob, "\" ");
222
+ bufputs(ob, link_attr);
223
+ bufputc(ob, '>');
224
+ } else {
225
+ BUFPUTSL(ob, "\">");
226
+ }
227
+
228
+ link_text_cb(ob, link, payload);
229
+ BUFPUTSL(ob, "</a>");
230
+
231
+ link_count++;
232
+ i = end + link_end;
233
+ end = i;
234
+ } else {
235
+ end = end + 1;
236
+ }
237
+ }
238
+
239
+ bufrelease(link);
240
+ return link_count;
241
+ }
242
+
243
+
244
+ /**
245
+ * Ruby code
246
+ */
41
247
  static void
42
248
  autolink_callback(struct buf *link_text, const struct buf *link, void *block)
43
249
  {
@@ -97,7 +303,7 @@ rb_rinku_autolink(int argc, VALUE *argv, VALUE self)
97
303
  {
98
304
  VALUE result, rb_text, rb_mode, rb_html, rb_block;
99
305
  struct buf input_buf = {0, 0, 0, 0, 0}, *output_buf;
100
- int link_mode;
306
+ int link_mode, count;
101
307
  const char *link_attr = NULL;
102
308
  ID mode_sym;
103
309
 
@@ -119,7 +325,7 @@ rb_rinku_autolink(int argc, VALUE *argv, VALUE self)
119
325
 
120
326
  input_buf.data = RSTRING_PTR(rb_text);
121
327
  input_buf.size = RSTRING_LEN(rb_text);
122
- output_buf = bufnew(128);
328
+ output_buf = bufnew(32);
123
329
 
124
330
  if (mode_sym == rb_intern("all"))
125
331
  link_mode = AUTOLINK_ALL;
@@ -131,26 +337,29 @@ rb_rinku_autolink(int argc, VALUE *argv, VALUE self)
131
337
  rb_raise(rb_eTypeError,
132
338
  "Invalid linking mode (possible values are :all, :urls, :email_addresses)");
133
339
 
134
- link_mode |= AUTOLINK_SANITIZE;
340
+ count = rinku_autolink(
341
+ output_buf,
342
+ &input_buf,
343
+ link_mode,
344
+ link_attr,
345
+ RTEST(rb_block) ? &autolink_callback : NULL,
346
+ (void*)rb_block);
135
347
 
136
- if (RTEST(rb_block))
137
- upshtml_autolink(output_buf, &input_buf, link_mode, link_attr, &autolink_callback, (void*)rb_block);
138
- else
139
- upshtml_autolink(output_buf, &input_buf, link_mode, link_attr, NULL, NULL);
348
+ if (count == 0)
349
+ result = rb_text;
350
+ else {
351
+ result = rb_str_new(output_buf->data, output_buf->size);
352
+ rb_enc_copy(result, rb_text);
353
+ }
140
354
 
141
- result = rb_str_new(output_buf->data, output_buf->size);
142
355
  bufrelease(output_buf);
143
-
144
- /* force the input encoding */
145
- rb_enc_copy(result, rb_text);
146
-
147
356
  return result;
148
357
  }
149
358
 
150
359
  void Init_rinku()
151
360
  {
152
- rb_cRinku = rb_define_class("Rinku", rb_cObject);
153
- rb_define_singleton_method(rb_cRinku, "auto_link", rb_rinku_autolink, -1);
361
+ rb_mRinku = rb_define_module("Rinku");
362
+ rb_define_method(rb_mRinku, "auto_link", rb_rinku_autolink, -1);
154
363
  }
155
364
 
156
365
 
data/lib/rails_rinku.rb CHANGED
@@ -1,35 +1,21 @@
1
1
  require 'rinku'
2
2
 
3
3
  module RailsRinku
4
- class Railtie < ::Rails::Railtie
5
- initializer 'rails_rinku' do |app|
6
- ActiveSupport.on_load(:action_view) do
7
- require 'active_support/core_ext/object/blank'
8
- require 'active_support/core_ext/array/extract_options'
9
- require 'active_support/core_ext/hash/reverse_merge'
10
- require 'active_support/core_ext/hash/keys'
4
+ def auto_link(text, *args, &block)
5
+ return ''.html_safe if text.blank?
11
6
 
12
- module ::ActionView
13
- module Helpers # :nodoc:
14
- module TextHelper
15
- def auto_link(text, *args, &block)
16
- return ''.html_safe if text.blank?
17
-
18
- options = args.size == 2 ? {} : args.extract_options!
19
- unless args.empty?
20
- options[:link] = args[0] || :all
21
- options[:html] = args[1] || {}
22
- end
23
- options.reverse_merge!(:link => :all, :html => {})
24
- text = sanitize(text) unless options[:sanitize] == false
25
-
26
- Rinku.auto_link(text, options[:link], tag_options(options[:html]), &block)
27
- end
28
- end
29
- end
30
- end
31
- end
7
+ options = args.size == 2 ? {} : args.extract_options!
8
+ unless args.empty?
9
+ options[:link] = args[0] || :all
10
+ options[:html] = args[1] || {}
32
11
  end
12
+ options.reverse_merge!(:link => :all, :html => {})
13
+ text = sanitize(text) unless options[:sanitize] == false
14
+
15
+ Rinku.auto_link(text, options[:link], tag_options(options[:html]), &block)
33
16
  end
34
17
  end
35
18
 
19
+ module ActionView::Helpers::TextHelper
20
+ include RailsRinku
21
+ end
data/lib/rinku.rb CHANGED
@@ -1,5 +1,6 @@
1
- class Rinku
2
- VERSION = "1.1.0"
1
+ module Rinku
2
+ VERSION = "1.2.0"
3
+ extend self
3
4
  end
4
5
 
5
6
  require 'rinku.so'
data/rinku.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'rinku'
3
- s.version = '1.1.0'
3
+ s.version = '1.2.0'
4
4
  s.summary = "Mostly autolinking"
5
5
  s.description = <<-EOF
6
6
  A fast and very smart autolinking library that
@@ -19,7 +19,6 @@ Gem::Specification.new do |s|
19
19
  ext/rinku/autolink.h
20
20
  ext/rinku/buffer.c
21
21
  ext/rinku/buffer.h
22
- ext/rinku/html_autolink.c
23
22
  ext/rinku/extconf.rb
24
23
  lib/rinku.rb
25
24
  lib/rails_rinku.rb
@@ -28,7 +28,7 @@ class RedcarpetAutolinkTest < Test::Unit::TestCase
28
28
  assert_equal "{link: #{link3_result}}", Rinku.auto_link("{link: #{link3_raw}}")
29
29
  end
30
30
 
31
- def test_auto_link_with_multiple_trailing_punctuations
31
+ def test_auto_link_with_multiple_trailing_punctuations
32
32
  url = "http://youtube.com"
33
33
  url_result = generate_result(url)
34
34
  assert_equal url_result, Rinku.auto_link(url)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rinku
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 1.1.0
10
+ version: 1.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - "Vicent Mart\xC3\xAD"
@@ -15,7 +15,8 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-11 00:00:00 Z
18
+ date: 2011-06-11 00:00:00 +02:00
19
+ default_executable:
19
20
  dependencies: []
20
21
 
21
22
  description: " A fast and very smart autolinking library that\n acts as a drop-in replacement for Rails `auto_link`\n"
@@ -35,12 +36,12 @@ files:
35
36
  - ext/rinku/autolink.h
36
37
  - ext/rinku/buffer.c
37
38
  - ext/rinku/buffer.h
38
- - ext/rinku/html_autolink.c
39
39
  - ext/rinku/extconf.rb
40
40
  - lib/rinku.rb
41
41
  - lib/rails_rinku.rb
42
42
  - rinku.gemspec
43
43
  - test/autolink_test.rb
44
+ has_rdoc: true
44
45
  homepage: http://github.com/tanoku/rinku
45
46
  licenses: []
46
47
 
@@ -70,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
70
71
  requirements: []
71
72
 
72
73
  rubyforge_project:
73
- rubygems_version: 1.8.5
74
+ rubygems_version: 1.6.2
74
75
  signing_key:
75
76
  specification_version: 3
76
77
  summary: Mostly autolinking
@@ -1,226 +0,0 @@
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 "autolink.h"
18
- #include "buffer.h"
19
-
20
- #include <string.h>
21
- #include <stdlib.h>
22
- #include <stdio.h>
23
- #include <ctype.h>
24
-
25
- static void
26
- autolink_escape_cb(struct buf *ob, const struct buf *text, void *unused)
27
- {
28
- size_t i = 0, org;
29
-
30
- while (i < text->size) {
31
- org = i;
32
-
33
- while (i < text->size &&
34
- text->data[i] != '<' &&
35
- text->data[i] != '>' &&
36
- text->data[i] != '&' &&
37
- text->data[i] != '"')
38
- i++;
39
-
40
- if (i > org)
41
- bufput(ob, text->data + org, i - org);
42
-
43
- if (i >= text->size)
44
- break;
45
-
46
- switch (text->data[i]) {
47
- case '<': BUFPUTSL(ob, "&lt;"); break;
48
- case '>': BUFPUTSL(ob, "&gt;"); break;
49
- case '&': BUFPUTSL(ob, "&amp;"); break;
50
- case '"': BUFPUTSL(ob, "&quot;"); break;
51
- default: bufputc(ob, text->data[i]); break;
52
- }
53
-
54
- i++;
55
- }
56
- }
57
-
58
- static inline int
59
- is_closing_a(const char *tag, size_t size)
60
- {
61
- size_t i;
62
-
63
- if (tag[0] != '<' || size < STRLEN("</a>") || tag[1] != '/')
64
- return 0;
65
-
66
- i = 2;
67
-
68
- while (i < size && isspace(tag[i]))
69
- i++;
70
-
71
- if (i == size || tag[i] != 'a')
72
- return 0;
73
-
74
- i++;
75
-
76
- while (i < size && isspace(tag[i]))
77
- i++;
78
-
79
- if (i == size || tag[i] != '>')
80
- return 0;
81
-
82
- return i;
83
- }
84
-
85
- static size_t
86
- autolink__skip_tag(struct buf *ob, char *text, size_t size)
87
- {
88
- size_t i = 0;
89
-
90
- while (i < size && text[i] != '>')
91
- i++;
92
-
93
- if (size > 3 && text[1] == 'a' && isspace(text[2])) {
94
- while (i < size) {
95
- size_t tag_len = is_closing_a(text + i, size - i);
96
- if (tag_len) {
97
- i += tag_len;
98
- break;
99
- }
100
- i++;
101
- }
102
- }
103
-
104
- bufput(ob, text, i + 1);
105
- return i + 1;
106
- }
107
-
108
- typedef size_t (*autolink_parse_cb)(size_t *rewind, struct buf *, char *, size_t, size_t);
109
-
110
- typedef enum {
111
- AUTOLINK_ACTION_NONE = 0,
112
- AUTOLINK_ACTION_WWW,
113
- AUTOLINK_ACTION_EMAIL,
114
- AUTOLINK_ACTION_URL,
115
- AUTOLINK_ACTION_SKIP_TAG
116
- } autolink_action;
117
-
118
- static autolink_parse_cb g_callbacks[] = {
119
- NULL,
120
- ups_autolink__www, /* 1 */
121
- ups_autolink__email,/* 2 */
122
- ups_autolink__url, /* 3 */
123
- };
124
-
125
- static const char *g_hrefs[] = {
126
- NULL,
127
- "<a href=\"http://",
128
- "<a href=\"mailto:",
129
- "<a href=\"",
130
- };
131
-
132
- void
133
- upshtml_autolink(
134
- struct buf *ob,
135
- struct buf *text,
136
- unsigned int flags,
137
- const char *link_attr,
138
- void (*link_text_cb)(struct buf *ob, const struct buf *link, void *payload),
139
- void *payload)
140
- {
141
- size_t i, end;
142
- struct buf *link = bufnew(16);
143
- char active_chars[256];
144
- void (*link_url_cb)(struct buf *, const struct buf *, void *);
145
-
146
- if (!text || text->size == 0)
147
- return;
148
-
149
- memset(active_chars, 0x0, sizeof(active_chars));
150
-
151
- active_chars['<'] = AUTOLINK_ACTION_SKIP_TAG;
152
-
153
- if (flags & AUTOLINK_EMAILS)
154
- active_chars['@'] = AUTOLINK_ACTION_EMAIL;
155
-
156
- if (flags & AUTOLINK_URLS) {
157
- active_chars['w'] = AUTOLINK_ACTION_WWW;
158
- active_chars['W'] = AUTOLINK_ACTION_WWW;
159
- active_chars[':'] = AUTOLINK_ACTION_URL;
160
- }
161
-
162
- if (link_text_cb == NULL)
163
- link_text_cb = &autolink_escape_cb;
164
-
165
- if (link_attr != NULL) {
166
- while (isspace(*link_attr))
167
- link_attr++;
168
- }
169
-
170
- bufgrow(ob, text->size);
171
-
172
- i = end = 0;
173
-
174
- while (i < text->size) {
175
- size_t rewind;
176
- char action;
177
-
178
- while (end < text->size && (action = active_chars[(int)text->data[end]]) == 0)
179
- end++;
180
-
181
- bufput(ob, text->data + i, end - i);
182
-
183
- if (end >= text->size)
184
- break;
185
-
186
- i = end;
187
- end = 0;
188
- link->size = 0;
189
-
190
- if (action == AUTOLINK_ACTION_SKIP_TAG) {
191
- end = autolink__skip_tag(ob, text->data + i, text->size - i);
192
- } else {
193
- end = g_callbacks[(int)action](&rewind, link, text->data + i, i, text->size - i);
194
-
195
- /* print the link */
196
- if (end > 0) {
197
- ob->size -= rewind;
198
-
199
- bufputs(ob, g_hrefs[(int)action]);
200
- autolink_escape_cb(ob, link, NULL);
201
-
202
- if (link_attr) {
203
- BUFPUTSL(ob, "\" ");
204
- bufputs(ob, link_attr);
205
- bufputc(ob, '>');
206
- } else {
207
- BUFPUTSL(ob, "\">");
208
- }
209
-
210
- link_text_cb(ob, link, payload);
211
- BUFPUTSL(ob, "</a>");
212
- }
213
- }
214
-
215
- if (!end)
216
- end = i + 1;
217
- else {
218
- i += end;
219
- end = i;
220
- }
221
- }
222
-
223
- bufrelease(link);
224
- }
225
-
226
-