zendesk-rinku 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NjJhYWM1MmUzNzc3MDI5NzliOWYxMDg0MWUyZTQzYzUxNzU0NmQ4Yw==
5
+ data.tar.gz: !binary |-
6
+ ZDg3N2VhMzc0MDc5MDQ1ZGFmYzAwNjJiNDk2MDVhYmQ4ZjA2OWViYg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NTI4ODlhMjg1OTRlODc3OGRhMDlmMDM2ZGYxMzk5YWFhMjdlYzE3M2NkZjUz
10
+ Nzg1NTFiZGEyMzQ2ZDkzZDA0NzIwYTE2YmRmM2IzMmRiNzg4ZDU3YWJjOTcw
11
+ YjgwYmI5ZGVmNjJmMjBjOGYzNDg5NWM3MDUwMGUzNjVmMTM4NDc=
12
+ data.tar.gz: !binary |-
13
+ OTYxZTNmYjlkNWU3NGZjZmMxZDYxMmIzYjNkMWQ2YmIwNWY1M2MyOGYxYmZh
14
+ Yjc1ZWUwNjgxOWU1Y2JkN2NkY2ZiYzU5OGFmNWM3OGU1MDBjZjQ5ZmFlMjBi
15
+ NDkxNTRkYTc2NTM0Nzg1NTY0ZThmYmZhNDhjMDkxOWU2NTUwZWI=
data/COPYING ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2011, Vicent Marti
2
+
3
+ Permission to use, copy, modify, and distribute this software for any
4
+ purpose with or without fee is hereby granted, provided that the above
5
+ copyright notice and this permission notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,120 @@
1
+ Rinku does linking
2
+ ==================
3
+
4
+ Rinku is a Ruby library that does autolinking.
5
+ It parses text and turns anything that remotely resembles a link into an HTML link,
6
+ just like the Ruby on Rails `auto_link` method -- but it's about 20 times faster,
7
+ because it's written in C, and it's about 20 times smarter when linking,
8
+ because it does actual parsing instead of RegEx replacements.
9
+
10
+ Rinku is a Ruby Gem
11
+ -------------------
12
+
13
+ Rinku is available as a Ruby gem:
14
+
15
+ $ [sudo] gem install rinku
16
+
17
+ The Rinku source is available at GitHub:
18
+
19
+ $ git clone git://github.com/vmg/rinku.git
20
+
21
+ Rinku is a standalone library
22
+ -----------------------------
23
+
24
+ It exports a single method called `Rinku.auto_link`.
25
+
26
+ ~~~~~ruby
27
+ require 'rinku'
28
+
29
+ Rinku.auto_link(text, mode=:all, link_attr=nil, skip_tags=nil)
30
+ Rinku.auto_link(text, mode=:all, link_attr=nil, skip_tags=nil) { |link_text| ... }
31
+ ~~~~~~
32
+
33
+ Parses a block of text looking for "safe" urls or email addresses,
34
+ and turns them into HTML links with the given attributes.
35
+
36
+ NOTE: The block of text may or may not be HTML; if the text is HTML,
37
+ Rinku will skip the relevant tags to prevent double-linking and linking
38
+ inside `pre` blocks by default.
39
+
40
+ NOTE: If the input text is HTML, it's expected to be already escaped.
41
+ Rinku will perform no escaping.
42
+
43
+ NOTE: Currently the follow protocols are considered safe and are the
44
+ only ones that will be autolinked.
45
+
46
+ http:// https:// ftp:// mailto://
47
+
48
+ Email addresses are also autolinked by default. URLs without a protocol
49
+ specifier but starting with 'www.' will also be autolinked, defaulting to
50
+ the 'http://' protocol.
51
+
52
+ - `text` is a string in plain text or HTML markup. If the string is formatted in
53
+ HTML, Rinku is smart enough to skip the links that are already enclosed in `<a>`
54
+ tags.`
55
+
56
+ - `mode` is a symbol, either `:all`, `:urls` or `:email_addresses`,
57
+ which specifies which kind of links will be auto-linked.
58
+
59
+ - `link_attr` is a string containing the link attributes for each link that
60
+ will be generated. These attributes are not sanitized and will be include as-is
61
+ in each generated link, e.g.
62
+
63
+ ~~~~~ruby
64
+ auto_link('http://www.pokemon.com', :all, 'target="_blank"')
65
+ # => '<a href="http://www.pokemon.com" target="_blank">http://www.pokemon.com</a>'
66
+ ~~~~~
67
+
68
+ This string can be autogenerated from a hash using the Rails `tag_options` helper.
69
+
70
+ - `skip_tags` is a list of strings with the names of HTML tags that will be skipped
71
+ when autolinking. If `nil`, this defaults to the value of the global `Rinku.skip_tags`,
72
+ which is initially `["a", "pre", "code", "kbd", "script"]`.
73
+
74
+ - `&block` is an optional block argument. If a block is passed, it will
75
+ be yielded for each found link in the text, and its return value will be used instead
76
+ of the name of the link. E.g.
77
+
78
+ ~~~~~ruby
79
+ auto_link('Check it out at http://www.pokemon.com') do |url|
80
+ "THE POKEMAN WEBSITEZ"
81
+ end
82
+ # => 'Check it out at <a href="http://www.pokemon.com">THE POKEMAN WEBSITEZ</a>'
83
+ ~~~~~~
84
+
85
+ Rinku is a drop-in replacement for Rails 3.1 `auto_link`
86
+ ----------------------------------------------------
87
+
88
+ Auto-linking functionality has been removed from Rails 3.1,
89
+ and is instead offered as a standalone gem, `rails_autolink`. You can
90
+ choose to use Rinku instead.
91
+
92
+ ~~~~ruby
93
+ require 'rails_rinku'
94
+ ~~~~
95
+
96
+ The `rails_rinku` package monkeypatches Rails with an `auto_link` method that
97
+ mimics 100% the original one, parameter per parameter. It's just faster.
98
+
99
+ Rinku is written by me
100
+ ----------------------
101
+
102
+ I am Vicent Marti, and I wrote Rinku.
103
+ While Rinku is busy doing autolinks, you should be busy following me on twitter.
104
+ [`@vmg`](http://twitter.com/vmg). Do it.
105
+
106
+ Rinku has an awesome license
107
+ ----------------------------
108
+
109
+ Permission to use, copy, modify, and/or distribute this software for any
110
+ purpose with or without fee is hereby granted, provided that the above
111
+ copyright notice and this permission notice appear in all copies.
112
+
113
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
114
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
115
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
116
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
117
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
118
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
119
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
120
+
data/Rakefile ADDED
@@ -0,0 +1,67 @@
1
+ require 'date'
2
+ require 'rake/clean'
3
+ require 'rake/extensiontask'
4
+ require 'digest/md5'
5
+
6
+ task :default => :test
7
+
8
+ # ==========================================================
9
+ # Ruby Extension
10
+ # ==========================================================
11
+
12
+ Rake::ExtensionTask.new('rinku')
13
+
14
+ # ==========================================================
15
+ # Testing
16
+ # ==========================================================
17
+
18
+ require 'rake/testtask'
19
+ Rake::TestTask.new('test') do |t|
20
+ t.test_files = FileList['test/*_test.rb']
21
+ t.ruby_opts += ['-rubygems'] if defined? Gem
22
+ end
23
+ task 'test' => [:compile]
24
+
25
+ # PACKAGING =================================================================
26
+
27
+ require 'rubygems'
28
+ $spec = eval(File.read('rinku.gemspec'))
29
+
30
+ def package(ext='')
31
+ "pkg/rinku-#{$spec.version}" + ext
32
+ end
33
+
34
+ desc 'Build packages'
35
+ task :package => package('.gem')
36
+
37
+ desc 'Build and install as local gem'
38
+ task :install => package('.gem') do
39
+ sh "gem install #{package('.gem')}"
40
+ end
41
+
42
+ desc 'Update the gemspec'
43
+ task :update_gem => file('rinku.gemspec')
44
+
45
+ directory 'pkg/'
46
+
47
+ file package('.gem') => %w[pkg/ rinku.gemspec] + $spec.files do |f|
48
+ sh "gem build rinku.gemspec"
49
+ mv File.basename(f.name), f.name
50
+ end
51
+
52
+ # GEMSPEC HELPERS ==========================================================
53
+ task :gather => 'sundown/src/autolink.h' do |t|
54
+ files =
55
+ FileList[
56
+ 'sundown/src/{buffer,autolink}.h',
57
+ 'sundown/src/{buffer,autolink}.c',
58
+ ]
59
+ cp files, 'ext/rinku/',
60
+ :preserve => true,
61
+ :verbose => true
62
+ end
63
+
64
+
65
+ file 'sundown/src/autolink.h' do |t|
66
+ abort "The Sundown submodule is required."
67
+ end
@@ -0,0 +1,296 @@
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 "buffer.h"
18
+ #include "autolink.h"
19
+
20
+ #include <string.h>
21
+ #include <stdlib.h>
22
+ #include <stdio.h>
23
+ #include <ctype.h>
24
+
25
+ #if defined(_WIN32)
26
+ #define strncasecmp _strnicmp
27
+ #endif
28
+
29
+ int
30
+ sd_autolink_issafe(const uint8_t *link, size_t link_len)
31
+ {
32
+ static const size_t valid_uris_count = 5;
33
+ static const char *valid_uris[] = {
34
+ "/", "http://", "https://", "ftp://", "mailto:"
35
+ };
36
+
37
+ size_t i;
38
+
39
+ for (i = 0; i < valid_uris_count; ++i) {
40
+ size_t len = strlen(valid_uris[i]);
41
+
42
+ if (link_len > len &&
43
+ strncasecmp((char *)link, valid_uris[i], len) == 0 &&
44
+ isalnum(link[len]))
45
+ return 1;
46
+ }
47
+
48
+ return 0;
49
+ }
50
+
51
+ static size_t
52
+ autolink_delim(uint8_t *data, size_t link_end, size_t offset, size_t size)
53
+ {
54
+ uint8_t cclose, copen = 0;
55
+ size_t i;
56
+
57
+ for (i = 0; i < link_end; ++i)
58
+ if (data[i] == '<') {
59
+ link_end = i;
60
+ break;
61
+ }
62
+
63
+ while (link_end > 0) {
64
+ if (strchr("?!.,", data[link_end - 1]) != NULL)
65
+ link_end--;
66
+
67
+ else if (data[link_end - 1] == ';') {
68
+ size_t new_end = link_end - 2;
69
+
70
+ while (new_end > 0 && isalpha(data[new_end]))
71
+ new_end--;
72
+
73
+ if (new_end < link_end - 2 && data[new_end] == '&')
74
+ link_end = new_end;
75
+ else
76
+ link_end--;
77
+ }
78
+ else break;
79
+ }
80
+
81
+ if (link_end == 0)
82
+ return 0;
83
+
84
+ cclose = data[link_end - 1];
85
+
86
+ switch (cclose) {
87
+ case '"': copen = '"'; break;
88
+ case '\'': copen = '\''; break;
89
+ case ')': copen = '('; break;
90
+ case ']': copen = '['; break;
91
+ case '}': copen = '{'; break;
92
+ }
93
+
94
+ if (copen != 0) {
95
+ size_t closing = 0;
96
+ size_t opening = 0;
97
+ size_t i = 0;
98
+
99
+ /* Try to close the final punctuation sign in this same line;
100
+ * if we managed to close it outside of the URL, that means that it's
101
+ * not part of the URL. If it closes inside the URL, that means it
102
+ * is part of the URL.
103
+ *
104
+ * Examples:
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
+ * => http://www.pokemon.com/Pikachu_(Electric)
111
+ *
112
+ * foo http://www.pokemon.com/Pikachu_(Electric)) bar
113
+ * => http://www.pokemon.com/Pikachu_(Electric))
114
+ *
115
+ * (foo http://www.pokemon.com/Pikachu_(Electric)) bar
116
+ * => foo http://www.pokemon.com/Pikachu_(Electric)
117
+ */
118
+
119
+ while (i < link_end) {
120
+ if (data[i] == copen)
121
+ opening++;
122
+ else if (data[i] == cclose)
123
+ closing++;
124
+
125
+ i++;
126
+ }
127
+
128
+ if (closing != opening)
129
+ link_end--;
130
+ }
131
+
132
+ return link_end;
133
+ }
134
+
135
+ static size_t
136
+ check_domain(uint8_t *data, size_t size, int allow_short)
137
+ {
138
+ size_t i, np = 0;
139
+
140
+ if (!isalnum(data[0]))
141
+ return 0;
142
+
143
+ for (i = 1; i < size - 1; ++i) {
144
+ if (data[i] == '.') np++;
145
+ else if (!isalnum(data[i]) && data[i] != '-') break;
146
+ }
147
+
148
+ if (allow_short) {
149
+ /* We don't need a valid domain in the strict sense (with
150
+ * least one dot; so just make sure it's composed of valid
151
+ * domain characters and return the length of the the valid
152
+ * sequence. */
153
+ return i;
154
+ } else {
155
+ /* a valid domain needs to have at least a dot.
156
+ * that's as far as we get */
157
+ return np ? i : 0;
158
+ }
159
+ }
160
+
161
+ size_t
162
+ sd_autolink__www(
163
+ size_t *rewind_p,
164
+ struct buf *link,
165
+ uint8_t *data,
166
+ size_t offset,
167
+ size_t size,
168
+ unsigned int flags)
169
+ {
170
+ size_t link_end;
171
+
172
+ if (offset > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
173
+ return 0;
174
+
175
+ if (size < 4 || memcmp(data, "www.", strlen("www.")) != 0)
176
+ return 0;
177
+
178
+ link_end = check_domain(data, size, 0);
179
+
180
+ if (link_end == 0)
181
+ return 0;
182
+
183
+ while (link_end < size && !isspace(data[link_end]))
184
+ link_end++;
185
+
186
+ link_end = autolink_delim(data, link_end, offset, size);
187
+
188
+ if (link_end == 0)
189
+ return 0;
190
+
191
+ bufput(link, data, link_end);
192
+ *rewind_p = 0;
193
+
194
+ return (int)link_end;
195
+ }
196
+
197
+ size_t
198
+ sd_autolink__email(
199
+ size_t *rewind_p,
200
+ struct buf *link,
201
+ uint8_t *data,
202
+ size_t offset,
203
+ size_t size,
204
+ unsigned int flags)
205
+ {
206
+ size_t link_end, rewind;
207
+ int nb = 0, np = 0;
208
+
209
+ for (rewind = 0; rewind < offset; ++rewind) {
210
+ uint8_t c = data[-rewind - 1];
211
+
212
+ if (isalnum(c))
213
+ continue;
214
+
215
+ if (strchr(".+-_", c) != NULL)
216
+ continue;
217
+
218
+ break;
219
+ }
220
+
221
+ if (rewind == 0)
222
+ return 0;
223
+
224
+ for (link_end = 0; link_end < size; ++link_end) {
225
+ uint8_t c = data[link_end];
226
+
227
+ if (isalnum(c))
228
+ continue;
229
+
230
+ if (c == '@')
231
+ nb++;
232
+ else if (c == '.' && link_end < size - 1)
233
+ np++;
234
+ else if (c != '-' && c != '_')
235
+ break;
236
+ }
237
+
238
+ if (link_end < 2 || nb != 1 || np == 0)
239
+ return 0;
240
+
241
+ link_end = autolink_delim(data, link_end, offset, size);
242
+
243
+ if (link_end == 0)
244
+ return 0;
245
+
246
+ bufput(link, data - rewind, link_end + rewind);
247
+ *rewind_p = rewind;
248
+
249
+ return link_end;
250
+ }
251
+
252
+ size_t
253
+ sd_autolink__url(
254
+ size_t *rewind_p,
255
+ struct buf *link,
256
+ uint8_t *data,
257
+ size_t offset,
258
+ size_t size,
259
+ unsigned int flags)
260
+ {
261
+ size_t link_end, rewind = 0, domain_len;
262
+
263
+ if (size < 4 || data[1] != '/' || data[2] != '/')
264
+ return 0;
265
+
266
+ while (rewind < offset && isalpha(data[-rewind - 1]))
267
+ rewind++;
268
+
269
+ if (!sd_autolink_issafe(data - rewind, size + rewind))
270
+ return 0;
271
+
272
+ link_end = strlen("://");
273
+
274
+ domain_len = check_domain(
275
+ data + link_end,
276
+ size - link_end,
277
+ flags & SD_AUTOLINK_SHORT_DOMAINS);
278
+
279
+ if (domain_len == 0)
280
+ return 0;
281
+
282
+ link_end += domain_len;
283
+ while (link_end < size && !isspace(data[link_end]))
284
+ link_end++;
285
+
286
+ link_end = autolink_delim(data, link_end, offset, size);
287
+
288
+ if (link_end == 0)
289
+ return 0;
290
+
291
+ bufput(link, data - rewind, link_end + rewind);
292
+ *rewind_p = rewind;
293
+
294
+ return link_end;
295
+ }
296
+