twitter-text-relative 1.6.2.pre.3

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/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:newgem_simple, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:newgem_simple, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,826 @@
1
+ # encoding: utf-8
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+
4
+ class TestAutolink
5
+ include Twitter::Autolink
6
+ end
7
+
8
+ describe Twitter::Autolink do
9
+ def original_text; end
10
+ def url; end
11
+
12
+ describe "auto_link_custom" do
13
+ before do
14
+ @autolinked_text = TestAutolink.new.auto_link(original_text) if original_text
15
+ end
16
+
17
+ describe "username autolinking" do
18
+ context "username preceded by a space" do
19
+ def original_text; "hello @jacob"; end
20
+
21
+ it "should be linked" do
22
+ @autolinked_text.should link_to_screen_name('jacob')
23
+ end
24
+ end
25
+
26
+ context "username at beginning of line" do
27
+ def original_text; "@jacob you're cool"; end
28
+
29
+ it "should be linked" do
30
+ @autolinked_text.should link_to_screen_name('jacob')
31
+ end
32
+ end
33
+
34
+ context "username preceded by word character" do
35
+ def original_text; "meet@the beach"; end
36
+
37
+ it "should not be linked" do
38
+ Nokogiri::HTML(@autolinked_text).search('a').should be_empty
39
+ end
40
+ end
41
+
42
+ context "username preceded by non-word character" do
43
+ def original_text; "great.@jacob"; end
44
+
45
+ it "should be linked" do
46
+ @autolinked_text.should link_to_screen_name('jacob')
47
+ end
48
+ end
49
+
50
+ context "username containing non-word characters" do
51
+ def original_text; "@zach&^$%^"; end
52
+
53
+ it "should not be linked" do
54
+ @autolinked_text.should link_to_screen_name('zach')
55
+ end
56
+ end
57
+
58
+ context "username over twenty characters" do
59
+ def original_text
60
+ @twenty_character_username = "zach" * 5
61
+ "@" + @twenty_character_username + "1"
62
+ end
63
+
64
+ it "should not be linked" do
65
+ @autolinked_text.should link_to_screen_name(@twenty_character_username)
66
+ end
67
+ end
68
+
69
+ context "username followed by japanese" do
70
+ def original_text; "@jacobの"; end
71
+
72
+ it "should be linked" do
73
+ @autolinked_text.should link_to_screen_name('jacob')
74
+ end
75
+ end
76
+
77
+ context "username preceded by japanese" do
78
+ def original_text; "あ@matz"; end
79
+
80
+ it "should be linked" do
81
+ @autolinked_text.should link_to_screen_name('matz')
82
+ end
83
+ end
84
+
85
+ context "username surrounded by japanese" do
86
+ def original_text; "あ@yoshimiの"; end
87
+
88
+ it "should be linked" do
89
+ @autolinked_text.should link_to_screen_name('yoshimi')
90
+ end
91
+ end
92
+
93
+ context "username using full-width at-sign" do
94
+ def original_text
95
+ "#{[0xFF20].pack('U')}jacob"
96
+ end
97
+
98
+ it "should be linked" do
99
+ @autolinked_text.should link_to_screen_name('jacob')
100
+ end
101
+ end
102
+ end
103
+
104
+ describe "list path autolinking" do
105
+
106
+ context "when List is not available" do
107
+ it "should not be linked" do
108
+ @autolinked_text = TestAutolink.new.auto_link_usernames_or_lists("hello @jacob/my-list", :suppress_lists => true)
109
+ @autolinked_text.should_not link_to_list_path('jacob/my-list')
110
+ @autolinked_text.should include('my-list')
111
+ end
112
+ end
113
+
114
+ context "slug preceded by a space" do
115
+ def original_text; "hello @jacob/my-list"; end
116
+
117
+ it "should be linked" do
118
+ @autolinked_text.should link_to_list_path('jacob/my-list')
119
+ end
120
+ end
121
+
122
+ context "username followed by a slash but no list" do
123
+ def original_text; "hello @jacob/ my-list"; end
124
+
125
+ it "should NOT be linked" do
126
+ @autolinked_text.should_not link_to_list_path('jacob/my-list')
127
+ @autolinked_text.should link_to_screen_name('jacob')
128
+ end
129
+ end
130
+
131
+ context "empty username followed by a list" do
132
+ def original_text; "hello @/my-list"; end
133
+
134
+ it "should NOT be linked" do
135
+ Nokogiri::HTML(@autolinked_text).search('a').should be_empty
136
+ end
137
+ end
138
+
139
+ context "list slug at beginning of line" do
140
+ def original_text; "@jacob/my-list"; end
141
+
142
+ it "should be linked" do
143
+ @autolinked_text.should link_to_list_path('jacob/my-list')
144
+ end
145
+ end
146
+
147
+ context "username preceded by alpha-numeric character" do
148
+ def original_text; "meet@the/beach"; end
149
+
150
+ it "should not be linked" do
151
+ Nokogiri::HTML(@autolinked_text).search('a').should be_empty
152
+ end
153
+ end
154
+
155
+ context "username preceded by non-word character" do
156
+ def original_text; "great.@jacob/my-list"; end
157
+
158
+ it "should be linked" do
159
+ @autolinked_text = TestAutolink.new.auto_link("great.@jacob/my-list")
160
+ @autolinked_text.should link_to_list_path('jacob/my-list')
161
+ end
162
+ end
163
+
164
+ context "username containing non-word characters" do
165
+ def original_text; "@zach/test&^$%^"; end
166
+
167
+ it "should be linked" do
168
+ @autolinked_text.should link_to_list_path('zach/test')
169
+ end
170
+ end
171
+
172
+ context "username over twenty characters" do
173
+ def original_text
174
+ @twentyfive_character_list = "jack/" + ("a" * 25)
175
+ "@#{@twentyfive_character_list}12345"
176
+ end
177
+
178
+ it "should be linked" do
179
+ @autolinked_text.should link_to_list_path(@twentyfive_character_list)
180
+ end
181
+ end
182
+ end
183
+
184
+ describe "hashtag autolinking" do
185
+ context "with an all numeric hashtag" do
186
+ def original_text; "#123"; end
187
+
188
+ it "should not be linked" do
189
+ @autolinked_text.should_not have_autolinked_hashtag('#123')
190
+ end
191
+ end
192
+
193
+ context "with a hashtag with alphanumeric characters" do
194
+ def original_text; "#ab1d"; end
195
+
196
+ it "should be linked" do
197
+ @autolinked_text.should have_autolinked_hashtag('#ab1d')
198
+ end
199
+ end
200
+
201
+ context "with a hashtag with underscores" do
202
+ def original_text; "#a_b_c_d"; end
203
+
204
+ it "should be linked" do
205
+ @autolinked_text.should have_autolinked_hashtag(original_text)
206
+ end
207
+ end
208
+
209
+ context "with a hashtag that is preceded by a word character" do
210
+ def original_text; "ab#cd"; end
211
+
212
+ it "should not be linked" do
213
+ @autolinked_text.should_not have_autolinked_hashtag(original_text)
214
+ end
215
+ end
216
+
217
+ context "with a page anchor in a url" do
218
+ def original_text; "Here's my url: http://foobar.com/#home"; end
219
+
220
+ it "should not link the hashtag" do
221
+ @autolinked_text.should_not have_autolinked_hashtag('#home')
222
+ end
223
+
224
+ it "should link the url" do
225
+ @autolinked_text.should have_autolinked_url('http://foobar.com/#home')
226
+ end
227
+ end
228
+
229
+ context "with a hashtag that starts with a number but has word characters" do
230
+ def original_text; "#2ab"; end
231
+
232
+ it "should be linked" do
233
+ @autolinked_text.should have_autolinked_hashtag(original_text)
234
+ end
235
+ end
236
+
237
+ context "with multiple valid hashtags" do
238
+ def original_text; "I'm frickin' awesome #ab #cd #ef"; end
239
+
240
+ it "links each hashtag" do
241
+ @autolinked_text.should have_autolinked_hashtag('#ab')
242
+ @autolinked_text.should have_autolinked_hashtag('#cd')
243
+ @autolinked_text.should have_autolinked_hashtag('#ef')
244
+ end
245
+ end
246
+
247
+ context "with a hashtag preceded by a ." do
248
+ def original_text; "ok, great.#abc"; end
249
+
250
+ it "should be linked" do
251
+ @autolinked_text.should have_autolinked_hashtag('#abc')
252
+ end
253
+ end
254
+
255
+ context "with a hashtag preceded by a &" do
256
+ def original_text; "&#nbsp;"; end
257
+
258
+ it "should not be linked" do
259
+ @autolinked_text.should_not have_autolinked_hashtag('#nbsp;')
260
+ end
261
+ end
262
+
263
+ context "with a hashtag that ends in an !" do
264
+ def original_text; "#great!"; end
265
+
266
+ it "should be linked, but should not include the !" do
267
+ @autolinked_text.should have_autolinked_hashtag('#great')
268
+ end
269
+ end
270
+
271
+ context "with a hashtag followed by Japanese" do
272
+ def original_text; "#twj_devの"; end
273
+
274
+ it "should be linked" do
275
+ @autolinked_text.should have_autolinked_hashtag('#twj_devの')
276
+ end
277
+ end
278
+
279
+ context "with a hashtag preceded by a full-width space" do
280
+ def original_text; "#{[0x3000].pack('U')}#twj_dev"; end
281
+
282
+ it "should be linked" do
283
+ @autolinked_text.should have_autolinked_hashtag('#twj_dev')
284
+ end
285
+ end
286
+
287
+ context "with a hashtag followed by a full-width space" do
288
+ def original_text; "#twj_dev#{[0x3000].pack('U')}"; end
289
+
290
+ it "should be linked" do
291
+ @autolinked_text.should have_autolinked_hashtag('#twj_dev')
292
+ end
293
+ end
294
+
295
+ context "with a hashtag using full-width hash" do
296
+ def original_text; "#{[0xFF03].pack('U')}twj_dev"; end
297
+
298
+ it "should be linked" do
299
+ link = Nokogiri::HTML(@autolinked_text).search('a')
300
+ (link.inner_text.respond_to?(:force_encoding) ? link.inner_text.force_encoding("utf-8") : link.inner_text).should == "#{[0xFF03].pack('U')}twj_dev"
301
+ link.first['href'].should == 'https://twitter.com/#!/search?q=%23twj_dev'
302
+ end
303
+ end
304
+
305
+ context "with a hashtag containing an accented latin character" do
306
+ def original_text
307
+ # the hashtag is #éhashtag
308
+ "##{[0x00e9].pack('U')}hashtag"
309
+ end
310
+
311
+ it "should be linked" do
312
+ @autolinked_text.should == "<a class=\"tweet-url hashtag\" href=\"https://twitter.com/#!/search?q=%23éhashtag\" rel=\"nofollow\" title=\"#éhashtag\">#éhashtag</a>"
313
+ end
314
+ end
315
+
316
+ end
317
+
318
+ describe "URL autolinking" do
319
+ def url; "http://www.google.com"; end
320
+
321
+ context "when embedded in plain text" do
322
+ def original_text; "On my search engine #{url} I found good links."; end
323
+
324
+ it "should be linked" do
325
+ @autolinked_text.should have_autolinked_url(url)
326
+ end
327
+ end
328
+
329
+ context "when surrounded by Japanese;" do
330
+ def original_text; "いまなにしてる#{url}いまなにしてる"; end
331
+
332
+ it "should be linked" do
333
+ @autolinked_text.should have_autolinked_url(url)
334
+ end
335
+ end
336
+
337
+ context "with a path surrounded by parentheses;" do
338
+ def original_text; "I found a neatness (#{url})"; end
339
+
340
+ it "should be linked" do
341
+ @autolinked_text.should have_autolinked_url(url)
342
+ end
343
+
344
+ context "when the URL ends with a slash;" do
345
+ def url; "http://www.google.com/"; end
346
+
347
+ it "should be linked" do
348
+ @autolinked_text.should have_autolinked_url(url)
349
+ end
350
+ end
351
+
352
+ context "when the URL has a path;" do
353
+ def url; "http://www.google.com/fsdfasdf"; end
354
+
355
+ it "should be linked" do
356
+ @autolinked_text.should have_autolinked_url(url)
357
+ end
358
+ end
359
+ end
360
+
361
+ context "when path contains parens" do
362
+ def original_text; "I found a neatness (#{url})"; end
363
+
364
+ it "should be linked" do
365
+ @autolinked_text.should have_autolinked_url(url)
366
+ end
367
+
368
+ context "wikipedia" do
369
+ def url; "http://en.wikipedia.org/wiki/Madonna_(artist)"; end
370
+
371
+ it "should be linked" do
372
+ @autolinked_text.should have_autolinked_url(url)
373
+ end
374
+ end
375
+
376
+ context "IIS session" do
377
+ def url; "http://msdn.com/S(deadbeef)/page.htm"; end
378
+
379
+ it "should be linked" do
380
+ @autolinked_text.should have_autolinked_url(url)
381
+ end
382
+ end
383
+
384
+ context "unbalanced parens" do
385
+ def url; "http://example.com/i_has_a_("; end
386
+
387
+ it "should be linked" do
388
+ @autolinked_text.should have_autolinked_url("http://example.com/i_has_a_")
389
+ end
390
+ end
391
+
392
+ context "balanced parens with a double quote inside" do
393
+ def url; "http://foo.com/foo_(\")_bar" end
394
+
395
+ it "should be linked" do
396
+ @autolinked_text.should have_autolinked_url("http://foo.com/foo_")
397
+ end
398
+ end
399
+
400
+ context "balanced parens hiding XSS" do
401
+ def url; 'http://x.xx.com/("style="color:red"onmouseover="alert(1)' end
402
+
403
+ it "should be linked" do
404
+ @autolinked_text.should have_autolinked_url("http://x.xx.com/")
405
+ end
406
+ end
407
+ end
408
+
409
+ context "when preceded by a :" do
410
+ def original_text; "Check this out @hoverbird:#{url}"; end
411
+
412
+ it "should be linked" do
413
+ @autolinked_text.should have_autolinked_url(url)
414
+ end
415
+ end
416
+
417
+ context "with a URL ending in allowed punctuation" do
418
+ it "does not consume ending punctuation" do
419
+ matcher = TestAutolink.new
420
+ %w| ? ! , . : ; ] ) } = \ ' |.each do |char|
421
+ matcher.auto_link("#{url}#{char}").should have_autolinked_url(url)
422
+ end
423
+ end
424
+ end
425
+
426
+ context "with a URL preceded in forbidden characters" do
427
+ it "should be linked" do
428
+ matcher = TestAutolink.new
429
+ %w| \ ' / ! = |.each do |char|
430
+ matcher.auto_link("#{char}#{url}").should have_autolinked_url(url)
431
+ end
432
+ end
433
+ end
434
+
435
+ context "when embedded in a link tag" do
436
+ def original_text; "<link rel='true'>#{url}</link>"; end
437
+
438
+ it "should be linked" do
439
+ @autolinked_text.should have_autolinked_url(url)
440
+ end
441
+ end
442
+
443
+ context "with multiple URLs" do
444
+ def original_text; "http://www.links.org link at start of page, link at end http://www.foo.org"; end
445
+
446
+ it "should autolink each one" do
447
+ @autolinked_text.should have_autolinked_url('http://www.links.org')
448
+ @autolinked_text.should have_autolinked_url('http://www.foo.org')
449
+ end
450
+ end
451
+
452
+ context "with multiple URLs in different formats" do
453
+ def original_text; "http://foo.com https://bar.com http://mail.foobar.org"; end
454
+
455
+ it "should autolink each one, in the proper order" do
456
+ @autolinked_text.should have_autolinked_url('http://foo.com')
457
+ @autolinked_text.should have_autolinked_url('https://bar.com')
458
+ @autolinked_text.should have_autolinked_url('http://mail.foobar.org')
459
+ end
460
+ end
461
+
462
+ context "with a URL having a long TLD" do
463
+ def original_text; "Yahoo integriert Facebook http://golem.mobi/0912/71607.html"; end
464
+
465
+ it "should autolink it" do
466
+ @autolinked_text.should have_autolinked_url('http://golem.mobi/0912/71607.html')
467
+ end
468
+ end
469
+
470
+ context "with a url lacking the protocol" do
471
+ def original_text; "I like www.foobar.com dudes"; end
472
+
473
+ it "does not link at all" do
474
+ link = Nokogiri::HTML(@autolinked_text).search('a')
475
+ link.should be_empty
476
+ end
477
+ end
478
+
479
+ context "with a @ in a URL" do
480
+ context "with XSS attack" do
481
+ def original_text; 'http://x.xx.com/@"style="color:pink"onmouseover=alert(1)//'; end
482
+
483
+ it "should not allow XSS follwing @" do
484
+ @autolinked_text.should have_autolinked_url('http://x.xx.com/')
485
+ end
486
+ end
487
+
488
+ context "with a username not followed by a /" do
489
+ def original_text; 'http://example.com/@foobar'; end
490
+
491
+ it "should link url" do
492
+ @autolinked_text.should have_autolinked_url('http://example.com/@foobar')
493
+ end
494
+ end
495
+
496
+ context "with a username followed by a /" do
497
+ def original_text; 'http://example.com/@foobar/'; end
498
+
499
+ it "should not link the username but link full url" do
500
+ @autolinked_text.should have_autolinked_url('http://example.com/@foobar/')
501
+ @autolinked_text.should_not link_to_screen_name('foobar')
502
+ end
503
+ end
504
+ end
505
+
506
+ context "regex engine quirks" do
507
+ context "does not spiral out of control on repeated periods" do
508
+ def original_text; "Test a ton of periods http://example.com/path.........................................."; end
509
+
510
+ it "should autolink" do
511
+ @autolinked_text.should have_autolinked_url('http://example.com/path')
512
+ end
513
+ end
514
+
515
+ context "does not spiral out of control on repeated dashes" do
516
+ def original_text; "Single char file ext http://www.bestbuy.com/site/Currie+Technologies+-+Ezip+400+Scooter/9885188.p?id=1218189013070&skuId=9885188"; end
517
+
518
+ it "should autolink" do
519
+ @autolinked_text.should have_autolinked_url('http://www.bestbuy.com/site/Currie+Technologies+-+Ezip+400+Scooter/9885188.p?id=1218189013070&skuId=9885188')
520
+ end
521
+ end
522
+ end
523
+
524
+ end
525
+
526
+ describe "Autolink all" do
527
+ before do
528
+ @linker = TestAutolink.new
529
+ end
530
+
531
+ it "should allow url/hashtag overlap" do
532
+ auto_linked = @linker.auto_link("https://twitter.com/#search")
533
+ auto_linked.should have_autolinked_url('https://twitter.com/#search')
534
+ end
535
+
536
+ it "should not add invalid option in HTML tags" do
537
+ auto_linked = @linker.auto_link("https://twitter.com/ is a URL, not a hashtag", :hashtag_class => 'hashtag_classname')
538
+ auto_linked.should have_autolinked_url('https://twitter.com/')
539
+ auto_linked.should_not include('hashtag_class')
540
+ auto_linked.should_not include('hashtag_classname')
541
+ end
542
+
543
+ it "should autolink url/hashtag/mention in text with Unicode supplementary characters" do
544
+ auto_linked = @linker.auto_link("#{[0x10400].pack('U')} #hashtag #{[0x10400].pack('U')} @mention #{[0x10400].pack('U')} http://twitter.com/")
545
+ auto_linked.should have_autolinked_hashtag('#hashtag')
546
+ auto_linked.should link_to_screen_name('mention')
547
+ auto_linked.should have_autolinked_url('http://twitter.com/')
548
+ end
549
+ end
550
+
551
+ end
552
+
553
+ describe "autolinking options" do
554
+ before do
555
+ @linker = TestAutolink.new
556
+ end
557
+
558
+ it "should show display_url when :url_entities provided" do
559
+ linked = @linker.auto_link("http://t.co/0JG5Mcq", :url_entities => [{
560
+ "url" => "http://t.co/0JG5Mcq",
561
+ "display_url" => "blog.twitter.com/2011/05/twitte…",
562
+ "expanded_url" => "http://blog.twitter.com/2011/05/twitter-for-mac-update.html",
563
+ "indices" => [
564
+ 84,
565
+ 103
566
+ ]
567
+ }])
568
+ html = Nokogiri::HTML(linked)
569
+ html.search('a').should_not be_empty
570
+ html.search('a[@href="http://t.co/0JG5Mcq"]').should_not be_empty
571
+ html.search('span[@class=js-display-url]').inner_text.should == "blog.twitter.com/2011/05/twitte"
572
+ html.inner_text.should == " http://blog.twitter.com/2011/05/twitter-for-mac-update.html …"
573
+ html.search('span[@style="position:absolute;left:-9999px;"]').size.should == 4
574
+ end
575
+
576
+ it "should accept invisible_tag_attrs option" do
577
+ linked = @linker.auto_link("http://t.co/0JG5Mcq",
578
+ {
579
+ :url_entities => [{
580
+ "url" => "http://t.co/0JG5Mcq",
581
+ "display_url" => "blog.twitter.com/2011/05/twitte…",
582
+ "expanded_url" => "http://blog.twitter.com/2011/05/twitter-for-mac-update.html",
583
+ "indices" => [
584
+ 0,
585
+ 19
586
+ ]
587
+ }],
588
+ :invisible_tag_attrs => "style='dummy;'"
589
+ })
590
+ html = Nokogiri::HTML(linked)
591
+ html.search('span[@style="dummy;"]').size.should == 4
592
+ end
593
+
594
+ it "should show display_url if available in entity" do
595
+ linked = @linker.auto_link_entities("http://t.co/0JG5Mcq",
596
+ [{
597
+ :url => "http://t.co/0JG5Mcq",
598
+ :display_url => "blog.twitter.com/2011/05/twitte…",
599
+ :expanded_url => "http://blog.twitter.com/2011/05/twitter-for-mac-update.html",
600
+ :indices => [0, 19]
601
+ }]
602
+ )
603
+ html = Nokogiri::HTML(linked)
604
+ html.search('a').should_not be_empty
605
+ html.search('a[@href="http://t.co/0JG5Mcq"]').should_not be_empty
606
+ html.search('span[@class=js-display-url]').inner_text.should == "blog.twitter.com/2011/05/twitte"
607
+ html.inner_text.should == " http://blog.twitter.com/2011/05/twitter-for-mac-update.html …"
608
+ end
609
+
610
+ it "should apply :class as a CSS class" do
611
+ linked = @linker.auto_link("http://example.com/", :class => 'myclass')
612
+ linked.should have_autolinked_url('http://example.com/')
613
+ linked.should match(/myclass/)
614
+ end
615
+
616
+ it "should apply :url_class only on URL" do
617
+ linked = @linker.auto_link("http://twitter.com")
618
+ linked.should have_autolinked_url('http://twitter.com')
619
+ linked.should_not match(/class/)
620
+
621
+ linked = @linker.auto_link("http://twitter.com", :url_class => 'testClass')
622
+ linked.should have_autolinked_url('http://twitter.com')
623
+ linked.should match(/class=\"testClass\"/)
624
+
625
+ linked = @linker.auto_link("#hash @tw", :url_class => 'testClass')
626
+ linked.should match(/class=\"tweet-url hashtag\"/)
627
+ linked.should match(/class=\"tweet-url username\"/)
628
+ linked.should_not match(/class=\"testClass\"/)
629
+ end
630
+
631
+ it "should add rel=nofollow by default" do
632
+ linked = @linker.auto_link("http://example.com/")
633
+ linked.should have_autolinked_url('http://example.com/')
634
+ linked.should match(/nofollow/)
635
+ end
636
+
637
+ it "should include the '@' symbol in a username when passed :username_include_symbol" do
638
+ linked = @linker.auto_link("@user", :username_include_symbol => true)
639
+ linked.should link_to_screen_name('user', '@user')
640
+ end
641
+
642
+ it "should include the '@' symbol in a list when passed :username_include_symbol" do
643
+ linked = @linker.auto_link("@user/list", :username_include_symbol => true)
644
+ linked.should link_to_list_path('user/list', '@user/list')
645
+ end
646
+
647
+ it "should not add rel=nofollow when passed :suppress_no_follow" do
648
+ linked = @linker.auto_link("http://example.com/", :suppress_no_follow => true)
649
+ linked.should have_autolinked_url('http://example.com/')
650
+ linked.should_not match(/nofollow/)
651
+ end
652
+
653
+ it "should not add a target attribute by default" do
654
+ linked = @linker.auto_link("http://example.com/")
655
+ linked.should have_autolinked_url('http://example.com/')
656
+ linked.should_not match(/target=/)
657
+ end
658
+
659
+ it "should respect the :target option" do
660
+ linked = @linker.auto_link("http://example.com/", :target => 'mywindow')
661
+ linked.should have_autolinked_url('http://example.com/')
662
+ linked.should match(/target="mywindow"/)
663
+ end
664
+
665
+ it "should customize href by username_url_block option" do
666
+ linked = @linker.auto_link("@test", :username_url_block => lambda{|a| "dummy"})
667
+ linked.should have_autolinked_url('dummy', 'test')
668
+ end
669
+
670
+ it "should customize href by list_url_block option" do
671
+ linked = @linker.auto_link("@test/list", :list_url_block => lambda{|a| "dummy"})
672
+ linked.should have_autolinked_url('dummy', 'test/list')
673
+ end
674
+
675
+ it "should customize href by hashtag_url_block option" do
676
+ linked = @linker.auto_link("#hashtag", :hashtag_url_block => lambda{|a| "dummy"})
677
+ linked.should have_autolinked_url('dummy', '#hashtag')
678
+ end
679
+
680
+ it "should customize href by cashtag_url_block option" do
681
+ linked = @linker.auto_link("$CASH", :cashtag_url_block => lambda{|a| "dummy"})
682
+ linked.should have_autolinked_url('dummy', '$CASH')
683
+ end
684
+
685
+ it "should customize href by link_url_block option" do
686
+ linked = @linker.auto_link("http://example.com/", :link_url_block => lambda{|a| "dummy"})
687
+ linked.should have_autolinked_url('dummy', 'http://example.com/')
688
+ end
689
+
690
+ it "should modify link attributes by link_attribute_block" do
691
+ linked = @linker.auto_link("#hash @mention",
692
+ :link_attribute_block => lambda{|entity, attributes|
693
+ attributes[:"dummy-hash-attr"] = "test" if entity[:hashtag]
694
+ }
695
+ )
696
+ linked.should match(/<a[^>]+hashtag[^>]+dummy-hash-attr=\"test\"[^>]+>/)
697
+ linked.should_not match(/<a[^>]+username[^>]+dummy-hash-attr=\"test\"[^>]+>/)
698
+ linked.should_not match(/link_attribute_block/i)
699
+
700
+ linked = @linker.auto_link("@mention http://twitter.com/",
701
+ :link_attribute_block => lambda{|entity, attributes|
702
+ attributes["dummy-url-attr"] = entity[:url] if entity[:url]
703
+ }
704
+ )
705
+ linked.should_not match(/<a[^>]+username[^>]+dummy-url-attr=\"http:\/\/twitter.com\/\"[^>]*>/)
706
+ linked.should match(/<a[^>]+dummy-url-attr=\"http:\/\/twitter.com\/\"/)
707
+ end
708
+
709
+ it "should modify link text by link_text_block" do
710
+ linked = @linker.auto_link("#hash @mention",
711
+ :link_text_block => lambda{|entity, text|
712
+ entity[:hashtag] ? "#replaced" : "pre_#{text}_post"
713
+ }
714
+ )
715
+ linked.should match(/<a[^>]+>#replaced<\/a>/)
716
+ linked.should match(/<a[^>]+>pre_mention_post<\/a>/)
717
+
718
+ linked = @linker.auto_link("#hash @mention", {
719
+ :link_text_block => lambda{|entity, text|
720
+ "pre_#{text}_post"
721
+ },
722
+ :symbol_tag => "s", :text_with_symbol_tag => "b", :username_include_symbol => true
723
+ })
724
+ linked.should match(/<a[^>]+>pre_<s>#<\/s><b>hash<\/b>_post<\/a>/)
725
+ linked.should match(/<a[^>]+>pre_<s>@<\/s><b>mention<\/b>_post<\/a>/)
726
+ end
727
+
728
+ it "should apply :url_target only to auto-linked URLs" do
729
+ auto_linked = @linker.auto_link("#hashtag @mention http://test.com/", {:url_target => '_blank'})
730
+ auto_linked.should have_autolinked_hashtag('#hashtag')
731
+ auto_linked.should link_to_screen_name('mention')
732
+ auto_linked.should have_autolinked_url('http://test.com/')
733
+ auto_linked.should_not match(/<a[^>]+hashtag[^>]+target[^>]+>/)
734
+ auto_linked.should_not match(/<a[^>]+username[^>]+target[^>]+>/)
735
+ auto_linked.should match(/<a[^>]+test.com[^>]+target=\"_blank\"[^>]*>/)
736
+ end
737
+ end
738
+
739
+ describe "link_url_with_entity" do
740
+ before do
741
+ @linker = TestAutolink.new
742
+ end
743
+
744
+ it "should use display_url and expanded_url" do
745
+ @linker.send(:link_url_with_entity,
746
+ {
747
+ :url => "http://t.co/abcde",
748
+ :display_url => "twitter.com",
749
+ :expanded_url => "http://twitter.com/"},
750
+ {:invisible_tag_attrs => "class='invisible'"}).gsub('"', "'").should == "<span class='tco-ellipsis'><span class='invisible'>&nbsp;</span></span><span class='invisible'>http://</span><span class='js-display-url'>twitter.com</span><span class='invisible'>/</span><span class='tco-ellipsis'><span class='invisible'>&nbsp;</span></span>";
751
+ end
752
+
753
+ it "should correctly handle display_url ending with '…'" do
754
+ @linker.send(:link_url_with_entity,
755
+ {
756
+ :url => "http://t.co/abcde",
757
+ :display_url => "twitter.com…",
758
+ :expanded_url => "http://twitter.com/abcdefg"},
759
+ {:invisible_tag_attrs => "class='invisible'"}).gsub('"', "'").should == "<span class='tco-ellipsis'><span class='invisible'>&nbsp;</span></span><span class='invisible'>http://</span><span class='js-display-url'>twitter.com</span><span class='invisible'>/abcdefg</span><span class='tco-ellipsis'><span class='invisible'>&nbsp;</span>…</span>";
760
+ end
761
+
762
+ it "should correctly handle display_url starting with '…'" do
763
+ @linker.send(:link_url_with_entity,
764
+ {
765
+ :url => "http://t.co/abcde",
766
+ :display_url => "…tter.com/abcdefg",
767
+ :expanded_url => "http://twitter.com/abcdefg"},
768
+ {:invisible_tag_attrs => "class='invisible'"}).gsub('"', "'").should == "<span class='tco-ellipsis'>…<span class='invisible'>&nbsp;</span></span><span class='invisible'>http://twi</span><span class='js-display-url'>tter.com/abcdefg</span><span class='invisible'></span><span class='tco-ellipsis'><span class='invisible'>&nbsp;</span></span>";
769
+ end
770
+
771
+ it "should not create spans if display_url and expanded_url are on different domains" do
772
+ @linker.send(:link_url_with_entity,
773
+ {
774
+ :url => "http://t.co/abcde",
775
+ :display_url => "pic.twitter.com/xyz",
776
+ :expanded_url => "http://twitter.com/foo/statuses/123/photo/1"},
777
+ {:invisible_tag_attrs => "class='invisible'"}).gsub('"', "'").should == "pic.twitter.com/xyz"
778
+ end
779
+ end
780
+
781
+ describe "symbol_tag" do
782
+ before do
783
+ @linker = TestAutolink.new
784
+ end
785
+ it "should put :symbol_tag around symbol" do
786
+ @linker.auto_link("@mention", {:symbol_tag => 's', :username_include_symbol=>true}).should match(/<s>@<\/s>mention/)
787
+ @linker.auto_link("#hash", {:symbol_tag => 's'}).should match(/<s>#<\/s>hash/)
788
+ result = @linker.auto_link("@mention #hash $CASH", {:symbol_tag => 'b', :username_include_symbol=>true})
789
+ result.should match(/<b>@<\/b>mention/)
790
+ result.should match(/<b>#<\/b>hash/)
791
+ result.should match(/<b>\$<\/b>CASH/)
792
+ end
793
+ it "should put :text_with_symbol_tag around text" do
794
+ result = @linker.auto_link("@mention #hash $CASH", {:text_with_symbol_tag => 'b'})
795
+ result.should match(/<b>mention<\/b>/)
796
+ result.should match(/<b>hash<\/b>/)
797
+ result.should match(/<b>CASH<\/b>/)
798
+ end
799
+ it "should put :symbol_tag around symbol and :text_with_symbol_tag around text" do
800
+ result = @linker.auto_link("@mention #hash $CASH", {:symbol_tag => 's', :text_with_symbol_tag => 'b', :username_include_symbol=>true})
801
+ result.should match(/<s>@<\/s><b>mention<\/b>/)
802
+ result.should match(/<s>#<\/s><b>hash<\/b>/)
803
+ result.should match(/<s>\$<\/s><b>CASH<\/b>/)
804
+ end
805
+ end
806
+
807
+ describe "html_escape" do
808
+ before do
809
+ @linker = TestAutolink.new
810
+ end
811
+ it "should escape html entities properly" do
812
+ @linker.html_escape("&").should == "&amp;"
813
+ @linker.html_escape(">").should == "&gt;"
814
+ @linker.html_escape("<").should == "&lt;"
815
+ @linker.html_escape("\"").should == "&quot;"
816
+ @linker.html_escape("'").should == "&#39;"
817
+ @linker.html_escape("&<>\"").should == "&amp;&lt;&gt;&quot;"
818
+ @linker.html_escape("<div>").should == "&lt;div&gt;"
819
+ @linker.html_escape("a&b").should == "a&amp;b"
820
+ @linker.html_escape("<a href=\"https://twitter.com\" target=\"_blank\">twitter & friends</a>").should == "&lt;a href=&quot;https://twitter.com&quot; target=&quot;_blank&quot;&gt;twitter &amp; friends&lt;/a&gt;"
821
+ @linker.html_escape("&amp;").should == "&amp;amp;"
822
+ @linker.html_escape(nil).should == nil
823
+ end
824
+ end
825
+
826
+ end