flavicon 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +52 -0
- data/.rspec +2 -0
- data/.rubocop.yml +24 -0
- data/.ruby-version +1 -1
- data/.travis.yml +19 -4
- data/Gemfile +4 -14
- data/Gemfile.lock +65 -86
- data/README.md +4 -4
- data/Rakefile +4 -46
- data/flavicon.gemspec +25 -79
- data/lib/flavicon.rb +2 -0
- data/lib/flavicon/finder.rb +16 -5
- data/lib/flavicon/version.rb +5 -0
- metadata +28 -62
- data/spec/fixtures/absolute.html +0 -8
- data/spec/fixtures/missing.html +0 -8
- data/spec/fixtures/multiple.html +0 -9
- data/spec/fixtures/relative.html +0 -8
- data/spec/flavicon/finder_spec.rb +0 -192
- data/spec/flavicon_spec.rb +0 -18
- data/spec/spec_helper.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e563783a7460208b999fa27b864ed99b5601a14530013b1305aa4d7756f88fa3
|
4
|
+
data.tar.gz: 8da3ccc3dc46b41051f86ee134fd9607c84addae46b11ec1d75382a544d36ea9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e91756d0691ed894ce82608842f06e67a9a8489a655e0329e07e6797662780a8ac40352c135ed96fd429888e3e512b7094f6dfa9994113b6b267cf1aff8d978
|
7
|
+
data.tar.gz: 4e66b54722a0754f412ee4f46ac4f72d8a0f6ca652918917b1e6297529334d1a0816aadbc1507ae52bc9d25f73a2fa4271a96707391bb3edd795fd5c06259fd8
|
data/.gitignore
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# rcov generated
|
2
|
+
coverage
|
3
|
+
coverage.data
|
4
|
+
|
5
|
+
# rdoc generated
|
6
|
+
rdoc
|
7
|
+
|
8
|
+
# yard generated
|
9
|
+
doc
|
10
|
+
.yardoc
|
11
|
+
|
12
|
+
# bundler
|
13
|
+
.bundle
|
14
|
+
|
15
|
+
# jeweler generated
|
16
|
+
pkg
|
17
|
+
|
18
|
+
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
19
|
+
#
|
20
|
+
# * Create a file at ~/.gitignore
|
21
|
+
# * Include files you want ignored
|
22
|
+
# * Run: git config --global core.excludesfile ~/.gitignore
|
23
|
+
#
|
24
|
+
# After doing this, these files will be ignored in all your git projects,
|
25
|
+
# saving you from having to 'pollute' every project you touch with them
|
26
|
+
#
|
27
|
+
# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
|
28
|
+
#
|
29
|
+
# For MacOS:
|
30
|
+
#
|
31
|
+
#.DS_Store
|
32
|
+
|
33
|
+
# For TextMate
|
34
|
+
#*.tmproj
|
35
|
+
#tmtags
|
36
|
+
|
37
|
+
# For emacs:
|
38
|
+
#*~
|
39
|
+
#\#*
|
40
|
+
#.\#*
|
41
|
+
|
42
|
+
# For vim:
|
43
|
+
#*.swp
|
44
|
+
|
45
|
+
# For redcar:
|
46
|
+
#.redcar
|
47
|
+
|
48
|
+
# For rubinius:
|
49
|
+
#*.rbc
|
50
|
+
|
51
|
+
# For RubyMine
|
52
|
+
.idea
|
data/.rspec
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require: rubocop-rspec
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
TargetRubyVersion: 2.6
|
5
|
+
|
6
|
+
Metrics/LineLength:
|
7
|
+
Max: 120
|
8
|
+
|
9
|
+
Style/Documentation:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
Style/EmptyMethod:
|
13
|
+
EnforcedStyle: expanded
|
14
|
+
|
15
|
+
Style/FormatStringToken:
|
16
|
+
EnforcedStyle: template
|
17
|
+
|
18
|
+
Style/PercentLiteralDelimiters:
|
19
|
+
PreferredDelimiters:
|
20
|
+
default: ()
|
21
|
+
'%w': '()'
|
22
|
+
'%W': '()'
|
23
|
+
'%i': '()'
|
24
|
+
'%I': '()'
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.6.2
|
data/.travis.yml
CHANGED
@@ -1,6 +1,21 @@
|
|
1
|
+
---
|
2
|
+
sudo: false
|
3
|
+
env:
|
4
|
+
global:
|
5
|
+
- CC_TEST_REPORTER_ID=e365747cb5bcc556a4ce69b2deca895b8cc1a39601d63db9e3e82c83c9c9b39e
|
1
6
|
language: ruby
|
2
7
|
rvm:
|
3
|
-
-
|
4
|
-
- 2.
|
5
|
-
|
6
|
-
-
|
8
|
+
- 2.3
|
9
|
+
- 2.4
|
10
|
+
- 2.5
|
11
|
+
- 2.6
|
12
|
+
cache: bundler
|
13
|
+
before_install: gem install bundler -v 2.0.1
|
14
|
+
before_script:
|
15
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
16
|
+
- chmod +x ./cc-test-reporter
|
17
|
+
- ./cc-test-reporter before-build
|
18
|
+
script:
|
19
|
+
- bundle exec rspec
|
20
|
+
after_script:
|
21
|
+
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
data/Gemfile
CHANGED
@@ -1,16 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
source 'http://rubygems.org'
|
4
4
|
|
5
|
-
#
|
6
|
-
|
7
|
-
group :development do
|
8
|
-
gem 'rspec', '~> 2.14'
|
9
|
-
gem 'webmock', '~> 1.17'
|
10
|
-
gem 'rdoc', '~> 3.12'
|
11
|
-
gem 'bundler', '~> 1.0'
|
12
|
-
gem 'jeweler', '~> 2.0'
|
13
|
-
gem 'simplecov', '~> 0'
|
14
|
-
gem 'pry', '~> 0'
|
15
|
-
gem 'coveralls'
|
16
|
-
end
|
5
|
+
# Specify your gem's dependencies in flavicon.gemspec
|
6
|
+
gemspec
|
data/Gemfile.lock
CHANGED
@@ -1,104 +1,83 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
flavicon (0.2.0)
|
5
|
+
nokogiri (~> 1.10)
|
6
|
+
|
1
7
|
GEM
|
2
8
|
remote: http://rubygems.org/
|
3
9
|
specs:
|
4
|
-
addressable (2.
|
5
|
-
|
10
|
+
addressable (2.6.0)
|
11
|
+
public_suffix (>= 2.0.2, < 4.0)
|
12
|
+
ast (2.4.0)
|
6
13
|
coderay (1.1.0)
|
7
|
-
|
8
|
-
multi_json (~> 1.3)
|
9
|
-
rest-client
|
10
|
-
simplecov (>= 0.7)
|
11
|
-
term-ansicolor
|
12
|
-
thor
|
13
|
-
crack (0.4.2)
|
14
|
+
crack (0.4.3)
|
14
15
|
safe_yaml (~> 1.0.0)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
multipart-post (>= 1.2, < 3)
|
21
|
-
git (1.2.6)
|
22
|
-
github_api (0.11.3)
|
23
|
-
addressable (~> 2.3)
|
24
|
-
descendants_tracker (~> 0.0.1)
|
25
|
-
faraday (~> 0.8, < 0.10)
|
26
|
-
hashie (>= 1.2)
|
27
|
-
multi_json (>= 1.7.5, < 2.0)
|
28
|
-
nokogiri (~> 1.6.0)
|
29
|
-
oauth2
|
30
|
-
hashie (2.1.1)
|
31
|
-
highline (1.6.21)
|
32
|
-
jeweler (2.0.1)
|
33
|
-
builder
|
34
|
-
bundler (>= 1.0)
|
35
|
-
git (>= 1.2.5)
|
36
|
-
github_api
|
37
|
-
highline (>= 1.6.15)
|
38
|
-
nokogiri (>= 1.5.10)
|
39
|
-
rake
|
40
|
-
rdoc
|
41
|
-
json (1.8.1)
|
42
|
-
jwt (0.1.11)
|
43
|
-
multi_json (>= 1.5)
|
16
|
+
diff-lcs (1.3)
|
17
|
+
docile (1.3.1)
|
18
|
+
hashdiff (0.4.0)
|
19
|
+
jaro_winkler (1.5.2)
|
20
|
+
json (2.2.0)
|
44
21
|
method_source (0.8.2)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
mini_portile (~> 0.5.0)
|
52
|
-
oauth2 (0.9.3)
|
53
|
-
faraday (>= 0.8, < 0.10)
|
54
|
-
jwt (~> 0.1.8)
|
55
|
-
multi_json (~> 1.3)
|
56
|
-
multi_xml (~> 0.5)
|
57
|
-
rack (~> 1.2)
|
22
|
+
mini_portile2 (2.4.0)
|
23
|
+
nokogiri (1.10.3)
|
24
|
+
mini_portile2 (~> 2.4.0)
|
25
|
+
parallel (1.17.0)
|
26
|
+
parser (2.6.3.0)
|
27
|
+
ast (~> 2.4.0)
|
58
28
|
pry (0.9.12.6)
|
59
29
|
coderay (~> 1.0)
|
60
30
|
method_source (~> 0.8)
|
61
31
|
slop (~> 3.4)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
rspec (
|
69
|
-
rspec-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
rspec-
|
74
|
-
diff-lcs (>= 1.
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
32
|
+
public_suffix (3.1.0)
|
33
|
+
rainbow (3.0.0)
|
34
|
+
rspec (3.8.0)
|
35
|
+
rspec-core (~> 3.8.0)
|
36
|
+
rspec-expectations (~> 3.8.0)
|
37
|
+
rspec-mocks (~> 3.8.0)
|
38
|
+
rspec-core (3.8.0)
|
39
|
+
rspec-support (~> 3.8.0)
|
40
|
+
rspec-expectations (3.8.3)
|
41
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
42
|
+
rspec-support (~> 3.8.0)
|
43
|
+
rspec-mocks (3.8.0)
|
44
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
45
|
+
rspec-support (~> 3.8.0)
|
46
|
+
rspec-support (3.8.0)
|
47
|
+
rubocop (0.71.0)
|
48
|
+
jaro_winkler (~> 1.5.1)
|
49
|
+
parallel (~> 1.10)
|
50
|
+
parser (>= 2.6)
|
51
|
+
rainbow (>= 2.2.2, < 4.0)
|
52
|
+
ruby-progressbar (~> 1.7)
|
53
|
+
unicode-display_width (>= 1.4.0, < 1.7)
|
54
|
+
rubocop-rspec (1.33.0)
|
55
|
+
rubocop (>= 0.60.0)
|
56
|
+
ruby-progressbar (1.10.1)
|
57
|
+
safe_yaml (1.0.5)
|
58
|
+
simplecov (0.16.1)
|
59
|
+
docile (~> 1.1)
|
60
|
+
json (>= 1.8, < 3)
|
61
|
+
simplecov-html (~> 0.10.0)
|
62
|
+
simplecov-html (0.10.2)
|
82
63
|
slop (3.5.0)
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
thread_safe (0.3.3)
|
87
|
-
tins (1.1.0)
|
88
|
-
webmock (1.17.4)
|
89
|
-
addressable (>= 2.2.7)
|
64
|
+
unicode-display_width (1.6.0)
|
65
|
+
webmock (3.6.0)
|
66
|
+
addressable (>= 2.3.6)
|
90
67
|
crack (>= 0.3.2)
|
68
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
91
69
|
|
92
70
|
PLATFORMS
|
93
71
|
ruby
|
94
72
|
|
95
73
|
DEPENDENCIES
|
96
|
-
bundler (~>
|
97
|
-
|
98
|
-
jeweler (~> 2.0)
|
99
|
-
nokogiri (~> 1.6)
|
74
|
+
bundler (~> 2.0)
|
75
|
+
flavicon!
|
100
76
|
pry (~> 0)
|
101
|
-
|
102
|
-
rspec (~>
|
103
|
-
simplecov (~> 0)
|
104
|
-
webmock (~>
|
77
|
+
rspec (~> 3.8)
|
78
|
+
rubocop-rspec (~> 1.33)
|
79
|
+
simplecov (~> 0.16)
|
80
|
+
webmock (~> 3.6)
|
81
|
+
|
82
|
+
BUNDLED WITH
|
83
|
+
2.0.1
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
[![Build Status](https://travis-ci.org/hasghari/flavicon.
|
2
|
-
[![
|
3
|
-
[![Coverage
|
4
|
-
[![Gem Version](https://badge.fury.io/rb/flavicon.
|
1
|
+
[![Build Status](https://travis-ci.org/hasghari/flavicon.svg?branch=master)](https://travis-ci.org/hasghari/flavicon)
|
2
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/41fbe1dc447fe0deb33a/maintainability)](https://codeclimate.com/github/hasghari/flavicon/maintainability)
|
3
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/41fbe1dc447fe0deb33a/test_coverage)](https://codeclimate.com/github/hasghari/flavicon/test_coverage)
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/flavicon.svg)](http://badge.fury.io/rb/flavicon)
|
5
5
|
|
6
6
|
# flavicon
|
7
7
|
|
data/Rakefile
CHANGED
@@ -1,50 +1,8 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'bundler'
|
5
|
-
begin
|
6
|
-
Bundler.setup(:default, :development)
|
7
|
-
rescue Bundler::BundlerError => e
|
8
|
-
$stderr.puts e.message
|
9
|
-
$stderr.puts 'Run `bundle install` to install missing gems'
|
10
|
-
exit e.status_code
|
11
|
-
end
|
12
|
-
require 'rake'
|
13
|
-
|
14
|
-
require 'jeweler'
|
15
|
-
Jeweler::Tasks.new do |gem|
|
16
|
-
# gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
|
17
|
-
gem.name = 'flavicon'
|
18
|
-
gem.homepage = 'http://github.com/hasghari/flavicon'
|
19
|
-
gem.license = 'MIT'
|
20
|
-
gem.summary = 'fetch favicon url for provided url'
|
21
|
-
gem.description = 'fetch favicon url by parsing html and falling back on /favicon.ico as default'
|
22
|
-
gem.email = 'hasghari@gmail.com'
|
23
|
-
gem.authors = ['Hamed Asghari']
|
24
|
-
# dependencies defined in Gemfile
|
25
|
-
end
|
26
|
-
Jeweler::RubygemsDotOrgTasks.new
|
27
|
-
|
28
|
-
require 'rspec/core'
|
3
|
+
require 'bundler/gem_tasks'
|
29
4
|
require 'rspec/core/rake_task'
|
30
|
-
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
-
spec.pattern = FileList['spec/**/*_spec.rb']
|
32
|
-
end
|
33
|
-
|
34
|
-
desc 'Code coverage detail'
|
35
|
-
task :simplecov do
|
36
|
-
ENV['COVERAGE'] = 'true'
|
37
|
-
Rake::Task['spec'].execute
|
38
|
-
end
|
39
|
-
|
40
|
-
task :default => :spec
|
41
5
|
|
42
|
-
|
43
|
-
Rake::RDocTask.new do |rdoc|
|
44
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ''
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
45
7
|
|
46
|
-
|
47
|
-
rdoc.title = "flavicon #{version}"
|
48
|
-
rdoc.rdoc_files.include('README*')
|
49
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
50
|
-
end
|
8
|
+
task default: :spec
|
data/flavicon.gemspec
CHANGED
@@ -1,85 +1,31 @@
|
|
1
|
-
#
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
-
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: flavicon 0.1.1 ruby lib
|
1
|
+
# frozen_string_literal: true
|
6
2
|
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'flavicon/version'
|
10
6
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
s.email = "hasghari@gmail.com"
|
17
|
-
s.extra_rdoc_files = [
|
18
|
-
"LICENSE.txt",
|
19
|
-
"README.md"
|
20
|
-
]
|
21
|
-
s.files = [
|
22
|
-
".document",
|
23
|
-
".rspec",
|
24
|
-
".ruby-gemset",
|
25
|
-
".ruby-version",
|
26
|
-
".travis.yml",
|
27
|
-
"Gemfile",
|
28
|
-
"Gemfile.lock",
|
29
|
-
"LICENSE.txt",
|
30
|
-
"README.md",
|
31
|
-
"Rakefile",
|
32
|
-
"VERSION",
|
33
|
-
"flavicon.gemspec",
|
34
|
-
"lib/flavicon.rb",
|
35
|
-
"lib/flavicon/finder.rb",
|
36
|
-
"spec/fixtures/absolute.html",
|
37
|
-
"spec/fixtures/missing.html",
|
38
|
-
"spec/fixtures/multiple.html",
|
39
|
-
"spec/fixtures/relative.html",
|
40
|
-
"spec/flavicon/finder_spec.rb",
|
41
|
-
"spec/flavicon_spec.rb",
|
42
|
-
"spec/spec_helper.rb"
|
43
|
-
]
|
44
|
-
s.homepage = "http://github.com/hasghari/flavicon"
|
45
|
-
s.licenses = ["MIT"]
|
46
|
-
s.rubygems_version = "2.2.2"
|
47
|
-
s.summary = "fetch favicon url for provided url"
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'flavicon'
|
9
|
+
spec.version = Flavicon::VERSION
|
10
|
+
spec.authors = ['Hamed Asghari']
|
11
|
+
spec.email = ['hasghari@gmail.com']
|
48
12
|
|
49
|
-
|
50
|
-
|
13
|
+
spec.summary = 'fetch favicon url for provided url'
|
14
|
+
spec.description = 'fetch favicon url by parsing html and falling back on /favicon.ico as default'
|
15
|
+
spec.homepage = 'http://github.com/hasghari/flavicon'
|
16
|
+
spec.license = 'MIT'
|
51
17
|
|
52
|
-
|
53
|
-
|
54
|
-
s.add_development_dependency(%q<rspec>, ["~> 2.14"])
|
55
|
-
s.add_development_dependency(%q<webmock>, ["~> 1.17"])
|
56
|
-
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
57
|
-
s.add_development_dependency(%q<bundler>, ["~> 1.0"])
|
58
|
-
s.add_development_dependency(%q<jeweler>, ["~> 2.0"])
|
59
|
-
s.add_development_dependency(%q<simplecov>, ["~> 0"])
|
60
|
-
s.add_development_dependency(%q<pry>, ["~> 0"])
|
61
|
-
s.add_development_dependency(%q<coveralls>, [">= 0"])
|
62
|
-
else
|
63
|
-
s.add_dependency(%q<nokogiri>, ["~> 1.6"])
|
64
|
-
s.add_dependency(%q<rspec>, ["~> 2.14"])
|
65
|
-
s.add_dependency(%q<webmock>, ["~> 1.17"])
|
66
|
-
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
67
|
-
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
68
|
-
s.add_dependency(%q<jeweler>, ["~> 2.0"])
|
69
|
-
s.add_dependency(%q<simplecov>, ["~> 0"])
|
70
|
-
s.add_dependency(%q<pry>, ["~> 0"])
|
71
|
-
s.add_dependency(%q<coveralls>, [">= 0"])
|
72
|
-
end
|
73
|
-
else
|
74
|
-
s.add_dependency(%q<nokogiri>, ["~> 1.6"])
|
75
|
-
s.add_dependency(%q<rspec>, ["~> 2.14"])
|
76
|
-
s.add_dependency(%q<webmock>, ["~> 1.17"])
|
77
|
-
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
78
|
-
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
79
|
-
s.add_dependency(%q<jeweler>, ["~> 2.0"])
|
80
|
-
s.add_dependency(%q<simplecov>, ["~> 0"])
|
81
|
-
s.add_dependency(%q<pry>, ["~> 0"])
|
82
|
-
s.add_dependency(%q<coveralls>, [">= 0"])
|
18
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
19
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
83
20
|
end
|
84
|
-
|
21
|
+
spec.require_paths = ['lib']
|
22
|
+
|
23
|
+
spec.add_dependency 'nokogiri', '~> 1.10'
|
85
24
|
|
25
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
26
|
+
spec.add_development_dependency 'pry', '~> 0'
|
27
|
+
spec.add_development_dependency 'rspec', '~> 3.8'
|
28
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 1.33'
|
29
|
+
spec.add_development_dependency 'simplecov', '~> 0.16'
|
30
|
+
spec.add_development_dependency 'webmock', '~> 3.6'
|
31
|
+
end
|
data/lib/flavicon.rb
CHANGED
data/lib/flavicon/finder.rb
CHANGED
@@ -1,11 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Flavicon
|
2
|
-
class Finder
|
4
|
+
class Finder
|
3
5
|
require 'uri'
|
4
6
|
require 'net/http'
|
5
7
|
require 'nokogiri'
|
6
8
|
|
7
9
|
TooManyRedirects = Class.new(StandardError)
|
8
10
|
|
11
|
+
attr_reader :url
|
12
|
+
|
13
|
+
def initialize(url)
|
14
|
+
@url = url
|
15
|
+
end
|
16
|
+
|
9
17
|
def find
|
10
18
|
response, resolved = request(url)
|
11
19
|
favicon_url = extract_from_html(response.body, resolved) || default_path(resolved)
|
@@ -15,12 +23,13 @@ module Flavicon
|
|
15
23
|
def verify_favicon_url(url)
|
16
24
|
response, resolved = request(url)
|
17
25
|
return unless response.is_a?(Net::HTTPSuccess) && response.body.to_s != '' && response.content_type =~ /image/i
|
26
|
+
|
18
27
|
resolved
|
19
28
|
end
|
20
29
|
|
21
30
|
def extract_from_html(html, url)
|
22
|
-
link = Nokogiri::HTML(html).css('head link').find do |
|
23
|
-
|
31
|
+
link = Nokogiri::HTML(html).css('head link').find do |node|
|
32
|
+
node[:rel] =~ /\A(shortcut )?icon\z/i
|
24
33
|
end
|
25
34
|
|
26
35
|
URI.join(url, link[:href]).to_s if link
|
@@ -30,8 +39,9 @@ module Flavicon
|
|
30
39
|
URI.join(url, '/favicon.ico').to_s
|
31
40
|
end
|
32
41
|
|
42
|
+
# rubocop:disable Metrics/AbcSize,MethodLength
|
33
43
|
def request(url, limit = 10)
|
34
|
-
raise TooManyRedirects if limit
|
44
|
+
raise TooManyRedirects if limit.negative?
|
35
45
|
|
36
46
|
uri = URI.parse(url)
|
37
47
|
http = Net::HTTP.new(uri.host, uri.port)
|
@@ -47,9 +57,10 @@ module Flavicon
|
|
47
57
|
if response.is_a? Net::HTTPRedirection
|
48
58
|
request(extract_location(response, url), limit - 1)
|
49
59
|
else
|
50
|
-
|
60
|
+
[response, url]
|
51
61
|
end
|
52
62
|
end
|
63
|
+
# rubocop:enable Metrics/AbcSize,MethodLength
|
53
64
|
|
54
65
|
# While the soon-to-be obsolete IETF standard RFC 2616 (HTTP 1.1) requires a complete absolute URI for redirection,
|
55
66
|
# the most popular web browsers tolerate the passing of a relative URL as the value for a Location header field.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flavicon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hamed Asghari
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-06-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -16,137 +16,110 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.10'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
26
|
+
version: '1.10'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '2.14'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '2.14'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: webmock
|
28
|
+
name: bundler
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
44
30
|
requirements:
|
45
31
|
- - "~>"
|
46
32
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
33
|
+
version: '2.0'
|
48
34
|
type: :development
|
49
35
|
prerelease: false
|
50
36
|
version_requirements: !ruby/object:Gem::Requirement
|
51
37
|
requirements:
|
52
38
|
- - "~>"
|
53
39
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
40
|
+
version: '2.0'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
42
|
+
name: pry
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
58
44
|
requirements:
|
59
45
|
- - "~>"
|
60
46
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
47
|
+
version: '0'
|
62
48
|
type: :development
|
63
49
|
prerelease: false
|
64
50
|
version_requirements: !ruby/object:Gem::Requirement
|
65
51
|
requirements:
|
66
52
|
- - "~>"
|
67
53
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
54
|
+
version: '0'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
56
|
+
name: rspec
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
59
|
- - "~>"
|
74
60
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
61
|
+
version: '3.8'
|
76
62
|
type: :development
|
77
63
|
prerelease: false
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
79
65
|
requirements:
|
80
66
|
- - "~>"
|
81
67
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
68
|
+
version: '3.8'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
70
|
+
name: rubocop-rspec
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
86
72
|
requirements:
|
87
73
|
- - "~>"
|
88
74
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
75
|
+
version: '1.33'
|
90
76
|
type: :development
|
91
77
|
prerelease: false
|
92
78
|
version_requirements: !ruby/object:Gem::Requirement
|
93
79
|
requirements:
|
94
80
|
- - "~>"
|
95
81
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
82
|
+
version: '1.33'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: simplecov
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
100
86
|
requirements:
|
101
87
|
- - "~>"
|
102
88
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
89
|
+
version: '0.16'
|
104
90
|
type: :development
|
105
91
|
prerelease: false
|
106
92
|
version_requirements: !ruby/object:Gem::Requirement
|
107
93
|
requirements:
|
108
94
|
- - "~>"
|
109
95
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
96
|
+
version: '0.16'
|
111
97
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
98
|
+
name: webmock
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
114
100
|
requirements:
|
115
101
|
- - "~>"
|
116
102
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
103
|
+
version: '3.6'
|
118
104
|
type: :development
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
107
|
requirements:
|
122
108
|
- - "~>"
|
123
109
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: coveralls
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - ">="
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '0'
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - ">="
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '0'
|
110
|
+
version: '3.6'
|
139
111
|
description: fetch favicon url by parsing html and falling back on /favicon.ico as
|
140
112
|
default
|
141
|
-
email:
|
113
|
+
email:
|
114
|
+
- hasghari@gmail.com
|
142
115
|
executables: []
|
143
116
|
extensions: []
|
144
|
-
extra_rdoc_files:
|
145
|
-
- LICENSE.txt
|
146
|
-
- README.md
|
117
|
+
extra_rdoc_files: []
|
147
118
|
files:
|
148
119
|
- ".document"
|
120
|
+
- ".gitignore"
|
149
121
|
- ".rspec"
|
122
|
+
- ".rubocop.yml"
|
150
123
|
- ".ruby-gemset"
|
151
124
|
- ".ruby-version"
|
152
125
|
- ".travis.yml"
|
@@ -159,13 +132,7 @@ files:
|
|
159
132
|
- flavicon.gemspec
|
160
133
|
- lib/flavicon.rb
|
161
134
|
- lib/flavicon/finder.rb
|
162
|
-
-
|
163
|
-
- spec/fixtures/missing.html
|
164
|
-
- spec/fixtures/multiple.html
|
165
|
-
- spec/fixtures/relative.html
|
166
|
-
- spec/flavicon/finder_spec.rb
|
167
|
-
- spec/flavicon_spec.rb
|
168
|
-
- spec/spec_helper.rb
|
135
|
+
- lib/flavicon/version.rb
|
169
136
|
homepage: http://github.com/hasghari/flavicon
|
170
137
|
licenses:
|
171
138
|
- MIT
|
@@ -185,8 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
152
|
- !ruby/object:Gem::Version
|
186
153
|
version: '0'
|
187
154
|
requirements: []
|
188
|
-
|
189
|
-
rubygems_version: 2.2.2
|
155
|
+
rubygems_version: 3.0.3
|
190
156
|
signing_key:
|
191
157
|
specification_version: 4
|
192
158
|
summary: fetch favicon url for provided url
|
data/spec/fixtures/absolute.html
DELETED
data/spec/fixtures/missing.html
DELETED
data/spec/fixtures/multiple.html
DELETED
data/spec/fixtures/relative.html
DELETED
@@ -1,192 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
-
require 'flavicon/finder'
|
3
|
-
|
4
|
-
describe Flavicon::Finder do
|
5
|
-
def html(file)
|
6
|
-
File.read(File.expand_path(File.dirname(__FILE__) + "/../fixtures/#{file}"))
|
7
|
-
end
|
8
|
-
|
9
|
-
subject { Flavicon::Finder.new('http://www.ex.com') }
|
10
|
-
|
11
|
-
describe '#find' do
|
12
|
-
it 'should delegate to #request' do
|
13
|
-
response = double('response', body: html('absolute.html'))
|
14
|
-
subject.should_receive(:request).with('http://www.ex.com').and_return([response, 'http://www.other.com'])
|
15
|
-
subject.should_receive(:verify_favicon_url).and_return('http://sub.example.com/absolute.ico')
|
16
|
-
subject.find
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'should extract favicon from body' do
|
20
|
-
response = double('response', body: html('absolute.html'))
|
21
|
-
subject.should_receive(:request).with('http://www.ex.com').and_return([response, 'http://www.other.com'])
|
22
|
-
subject.should_receive(:verify_favicon_url).with('http://sub.example.com/absolute.ico')
|
23
|
-
.and_return('http://sub.example.com/absolute.ico')
|
24
|
-
subject.find.should == 'http://sub.example.com/absolute.ico'
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'should fallback to default when response is empty' do
|
28
|
-
response = double('response', body: '')
|
29
|
-
subject.should_receive(:request).with('http://www.ex.com').and_return([response, 'http://www.other.com'])
|
30
|
-
subject.should_receive(:verify_favicon_url).with('http://www.other.com/favicon.ico')
|
31
|
-
.and_return('http://www.other.com/favicon.ico')
|
32
|
-
subject.find.should == 'http://www.other.com/favicon.ico'
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'should return nil when not valid' do
|
36
|
-
response = double('response', body: html('absolute.html'))
|
37
|
-
subject.should_receive(:request).with('http://www.ex.com').and_return([response, 'http://www.other.com'])
|
38
|
-
subject.should_receive(:verify_favicon_url).and_return(nil)
|
39
|
-
subject.find.should be_nil
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe '#verify_favicon_url' do
|
44
|
-
let(:favicon_url) { 'http://www.ex.com/favicon.ico' }
|
45
|
-
let(:response) do
|
46
|
-
{ status: 200, body: 'blah', headers: { 'Content-Type' => 'image/x-icon'} }
|
47
|
-
end
|
48
|
-
|
49
|
-
before do
|
50
|
-
stub_request(:get, favicon_url).to_return(response)
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'should return favicon url' do
|
54
|
-
subject.verify_favicon_url(favicon_url).should == favicon_url
|
55
|
-
end
|
56
|
-
|
57
|
-
context 'http failure' do
|
58
|
-
let(:response) do
|
59
|
-
{ status: 400, body: 'blah', headers: { 'Content-Type' => 'image/x-icon'} }
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'should return nil' do
|
63
|
-
subject.verify_favicon_url(favicon_url).should be_nil
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
context 'empty body' do
|
68
|
-
let(:response) do
|
69
|
-
{ status: 200, body: '', headers: { 'Content-Type' => 'image/x-icon'} }
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'should return nil' do
|
73
|
-
subject.verify_favicon_url(favicon_url).should be_nil
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
context 'invalid content-type' do
|
78
|
-
let(:response) do
|
79
|
-
{ status: 200, body: 'blah', headers: { 'Content-Type' => 'text/javascript'} }
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'should return nil' do
|
83
|
-
subject.verify_favicon_url(favicon_url).should be_nil
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
describe '#extract_from_html' do
|
89
|
-
it 'should return nil for empty body' do
|
90
|
-
subject.extract_from_html('', 'http://www.ex.com').should be_nil
|
91
|
-
end
|
92
|
-
|
93
|
-
it 'should return nil if no favicon found' do
|
94
|
-
subject.extract_from_html(html('missing.html'), 'http://www.ex.com').should be_nil
|
95
|
-
end
|
96
|
-
|
97
|
-
it 'should handle absolute url' do
|
98
|
-
subject.extract_from_html(html('absolute.html'), 'http://www.ex.com')
|
99
|
-
.should == 'http://sub.example.com/absolute.ico'
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'should handle relative url' do
|
103
|
-
subject.extract_from_html(html('relative.html'), 'http://www.ex.com')
|
104
|
-
.should == 'http://www.ex.com/relative.ico'
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'should return first if multiple matches' do
|
108
|
-
subject.extract_from_html(html('multiple.html'), 'http://www.ex.com')
|
109
|
-
.should == 'http://www.ex.com/first.ico'
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
describe '#default_path' do
|
114
|
-
it 'should return default favicon url' do
|
115
|
-
subject.default_path('http://www.basic.com').should == 'http://www.basic.com/favicon.ico'
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'ignores query and fragment' do
|
119
|
-
subject.default_path('http://www.basic.com?query=a#fragment').should == 'http://www.basic.com/favicon.ico'
|
120
|
-
end
|
121
|
-
|
122
|
-
it 'ignores path with no trailing slash' do
|
123
|
-
subject.default_path('http://www.basic.com/basic').should == 'http://www.basic.com/favicon.ico'
|
124
|
-
end
|
125
|
-
|
126
|
-
it 'ignores path with trailing slash' do
|
127
|
-
subject.default_path('http://www.basic.com/basic/').should == 'http://www.basic.com/favicon.ico'
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
describe '#request' do
|
132
|
-
before do
|
133
|
-
stub_request(:get, 'http://www.ex.com/abc/')
|
134
|
-
.to_return(status: 200, body: '', headers: {})
|
135
|
-
end
|
136
|
-
|
137
|
-
it 'should raise error when redirect limit reached' do
|
138
|
-
expect {
|
139
|
-
subject.request('http://www.ex.com', -1)
|
140
|
-
}.to raise_error(Flavicon::Finder::TooManyRedirects)
|
141
|
-
end
|
142
|
-
|
143
|
-
it 'should return response and url when successful' do
|
144
|
-
response, url = subject.request('http://www.ex.com/abc/')
|
145
|
-
response.should be_a Net::HTTPSuccess
|
146
|
-
url.should == 'http://www.ex.com/abc/'
|
147
|
-
end
|
148
|
-
|
149
|
-
context 'ssl' do
|
150
|
-
before do
|
151
|
-
stub_request(:get, 'http://secure.ex.com:443/abc/')
|
152
|
-
.to_return(status: 200, body: '', headers: {})
|
153
|
-
end
|
154
|
-
|
155
|
-
it 'should set http secure state' do
|
156
|
-
Net::HTTP.any_instance.should_receive(:use_ssl=).with(true)
|
157
|
-
Net::HTTP.any_instance.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
|
158
|
-
response, url = subject.request('https://secure.ex.com/abc/')
|
159
|
-
response.should be_a Net::HTTPSuccess
|
160
|
-
url.should == 'https://secure.ex.com/abc/'
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
context 'redirect' do
|
165
|
-
before do
|
166
|
-
stub_request(:get, 'http://www.ex.com/abc')
|
167
|
-
.to_return(status: 301, body: '', headers: { 'Location' => 'http://www.ex.com/abc/' })
|
168
|
-
end
|
169
|
-
|
170
|
-
it 'should follow redirect responses' do
|
171
|
-
response, resolved = subject.request('http://www.ex.com/abc')
|
172
|
-
response.should be_a Net::HTTPSuccess
|
173
|
-
resolved.should == 'http://www.ex.com/abc/'
|
174
|
-
end
|
175
|
-
|
176
|
-
it 'should recurse' do
|
177
|
-
subject.should_receive(:request).with('http://www.ex.com/abc', 2).and_call_original
|
178
|
-
subject.should_receive(:request).with('http://www.ex.com/abc/', 1)
|
179
|
-
subject.request('http://www.ex.com/abc', 2)
|
180
|
-
end
|
181
|
-
|
182
|
-
it 'should handle relative redirect urls' do
|
183
|
-
stub_request(:get, 'http://www.ex.com/def')
|
184
|
-
.to_return(status: 301, body: '', headers: { 'Location' => '/ghi/' })
|
185
|
-
|
186
|
-
subject.should_receive(:request).with('http://www.ex.com/def').and_call_original
|
187
|
-
subject.should_receive(:request).with('http://www.ex.com/ghi/', 9)
|
188
|
-
subject.request('http://www.ex.com/def')
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
end
|
data/spec/flavicon_spec.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
require 'flavicon'
|
3
|
-
|
4
|
-
describe Flavicon do
|
5
|
-
describe '::find' do
|
6
|
-
it 'should delegate to Finder' do
|
7
|
-
double = double('Finder').as_null_object
|
8
|
-
Flavicon::Finder.should_receive(:new).with('http://www.example.com').and_return(double)
|
9
|
-
Flavicon.find('http://www.example.com')
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'should call find on Finder instance' do
|
13
|
-
double = double('Finder', find: 'http://www.example.com/favicon.ico')
|
14
|
-
Flavicon::Finder.should_receive(:new).with('http://www.example.com').and_return(double)
|
15
|
-
Flavicon.find('http://www.example.com').should eq('http://www.example.com/favicon.ico')
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
require 'simplecov'
|
2
|
-
require 'coveralls'
|
3
|
-
|
4
|
-
module SimpleCov::Configuration
|
5
|
-
def clean_filters
|
6
|
-
@filters = []
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
SimpleCov.configure do
|
11
|
-
clean_filters
|
12
|
-
load_profile 'test_frameworks'
|
13
|
-
end
|
14
|
-
|
15
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
16
|
-
SimpleCov::Formatter::HTMLFormatter,
|
17
|
-
Coveralls::SimpleCov::Formatter
|
18
|
-
]
|
19
|
-
|
20
|
-
ENV['COVERAGE'] && SimpleCov.start do
|
21
|
-
add_filter '/.rvm/'
|
22
|
-
end
|
23
|
-
|
24
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
25
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
26
|
-
|
27
|
-
require 'rspec'
|
28
|
-
require 'flavicon'
|
29
|
-
require 'pry'
|
30
|
-
|
31
|
-
require 'webmock/rspec'
|
32
|
-
WebMock.disable_net_connect!(allow_localhost: true)
|
33
|
-
|
34
|
-
# Requires supporting files with custom matchers and macros, etc,
|
35
|
-
# in ./support/ and its subdirectories.
|
36
|
-
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
37
|
-
|
38
|
-
RSpec.configure do |config|
|
39
|
-
config.order = 'random'
|
40
|
-
end
|