ficon 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/ficon +3 -1
- data/ficon.gemspec +8 -3
- data/lib/ficon/cache.rb +71 -0
- data/lib/ficon/image.rb +21 -0
- data/lib/ficon/version.rb +1 -1
- data/lib/ficon.rb +72 -59
- data/test/ficon_test.rb +37 -28
- metadata +81 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d372436b5875c04a175f7756bef99aa917c6faef
|
4
|
+
data.tar.gz: 4a2909fa1f1eaf5cb3dd6e300381950c084704df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f451fb54ae264f32cb07d5d67fb9c4b4858b75a60347963cb9885c043dd330933e8fcb65aac058feb12de33f0851cbf5b8dbd64722cf25022a4dbfd42032aca
|
7
|
+
data.tar.gz: 5c5cb399f0c832270690dc220c0d8a9c13c00c99dc3d095acdb7d907eb3fb77df67d787228bf8906f2fcfcd763e07c9944d42ee49b335c33c2faad6cba18d791
|
data/bin/ficon
CHANGED
data/ficon.gemspec
CHANGED
@@ -18,8 +18,13 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_runtime_dependency 'nokogiri', "~> 1.
|
21
|
+
spec.add_runtime_dependency 'nokogiri', "~> 1.7"
|
22
|
+
spec.add_runtime_dependency 'addressable', "~> 2"
|
23
|
+
spec.add_runtime_dependency 'fastimage', "~> 2"
|
24
|
+
spec.add_runtime_dependency 'sqlite3', "~> 1"
|
22
25
|
|
23
|
-
spec.add_development_dependency "bundler", "~> 1
|
24
|
-
spec.add_development_dependency "rake", "~>
|
26
|
+
spec.add_development_dependency "bundler", "~> 1"
|
27
|
+
spec.add_development_dependency "rake", "~> 12"
|
28
|
+
spec.add_development_dependency "minitest", "~> 5"
|
29
|
+
spec.add_development_dependency "byebug", "~> 9"
|
25
30
|
end
|
data/lib/ficon/cache.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'sqlite3'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Ficon
|
5
|
+
|
6
|
+
class Cache
|
7
|
+
def initialize(url)
|
8
|
+
@url = url.to_s
|
9
|
+
Cache.setup_cache(db) if db.execute( "SELECT name FROM sqlite_master WHERE type='table' AND name='urls'" ).length == 0
|
10
|
+
end
|
11
|
+
|
12
|
+
def db
|
13
|
+
_db = SQLite3::Database.new Cache.db_file
|
14
|
+
_db.busy_timeout=1000
|
15
|
+
return _db
|
16
|
+
end
|
17
|
+
|
18
|
+
def data
|
19
|
+
JSON.parse db.execute( "select data from urls where url=?limit 1", @url ).first&.first
|
20
|
+
rescue
|
21
|
+
return nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def data=(_value)
|
25
|
+
value = _value.to_json
|
26
|
+
db.execute("INSERT OR IGNORE INTO urls (url, data) VALUES (?, ?)", [@url, value])
|
27
|
+
db.execute("UPDATE urls SET data=? WHERE url=?", [value, @url])
|
28
|
+
end
|
29
|
+
|
30
|
+
def etag
|
31
|
+
JSON.parse db.execute( "select etag from urls where url=?limit 1", @url ).first&.first
|
32
|
+
rescue
|
33
|
+
return nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def etag=(_value)
|
37
|
+
value = _value.to_json
|
38
|
+
db.execute("INSERT OR IGNORE INTO urls (url, etag) VALUES (?, ?)", [@url, value])
|
39
|
+
db.execute("UPDATE urls SET etag=? WHERE url=?", [value, @url])
|
40
|
+
end
|
41
|
+
|
42
|
+
def not_before
|
43
|
+
JSON.parse db.execute( "select not_before from urls where url=?limit 1", @url ).first&.first
|
44
|
+
rescue
|
45
|
+
return nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def not_before=(_value)
|
49
|
+
value = _value.to_json
|
50
|
+
db.execute("INSERT OR IGNORE INTO urls (url, not_before) VALUES (?, ?)", [@url, value])
|
51
|
+
db.execute("UPDATE urls SET not_before=? WHERE url=?", [value, @url])
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.db_file
|
55
|
+
if ENV['FICON_DB'].nil?
|
56
|
+
File.expand_path('~/.ficon.db')
|
57
|
+
else
|
58
|
+
ENV['FICON_DB']
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.setup_cache(db)
|
63
|
+
db.execute("CREATE TABLE urls(url, etag, not_before, data)")
|
64
|
+
db.execute("CREATE UNIQUE INDEX `url` ON `urls` (`url`)")
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
|
data/lib/ficon/image.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'fastimage'
|
3
|
+
|
4
|
+
module Ficon
|
5
|
+
class Image
|
6
|
+
require 'fastimage'
|
7
|
+
|
8
|
+
attr_reader :url, :size, :area
|
9
|
+
def initialize(url)
|
10
|
+
@url = url
|
11
|
+
c = Cache.new(@url)
|
12
|
+
@size = Cache.new(url).data || FastImage.size(url)
|
13
|
+
c.data = @size
|
14
|
+
@area = @size&.inject(&:*) || 0
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
@url.to_s + "(#{@size})"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/ficon/version.rb
CHANGED
data/lib/ficon.rb
CHANGED
@@ -1,29 +1,39 @@
|
|
1
|
-
require "ficon/version"
|
2
|
-
|
3
1
|
require 'open-uri'
|
4
2
|
require 'nokogiri'
|
5
3
|
require 'uri'
|
6
|
-
require
|
4
|
+
require "ostruct"
|
5
|
+
require 'addressable/uri'
|
6
|
+
require 'byebug'
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
require_relative 'ficon/version'
|
9
|
+
require_relative 'ficon/image'
|
10
|
+
require_relative 'ficon/cache'
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
module Ficon
|
13
|
+
class Site
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
uri = Addressable::URI.heuristic_parse(
|
17
|
-
|
18
|
-
|
15
|
+
attr_reader :site
|
16
|
+
def initialize(uri)
|
17
|
+
@uri = Addressable::URI.heuristic_parse(uri)
|
18
|
+
@site = OpenStruct.new
|
19
|
+
process
|
19
20
|
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
doc = Nokogiri::HTML(data)
|
24
|
-
|
25
|
-
uri = data.base_uri
|
22
|
+
def doc
|
23
|
+
cache = Cache.new(@uri)
|
26
24
|
|
25
|
+
@data ||= cache.data
|
26
|
+
|
27
|
+
if @data.nil?
|
28
|
+
@data = open(@uri)
|
29
|
+
cache.data = @data.read
|
30
|
+
cache.etag = @data.meta['etag'] if @data.respond_to?(:meta)
|
31
|
+
cache.not_before = @data.meta['last-modified'] if @data.respond_to?(:meta)
|
32
|
+
@data.rewind
|
33
|
+
end
|
34
|
+
|
35
|
+
@doc ||= Nokogiri::HTML(@data)
|
36
|
+
return @doc
|
27
37
|
rescue OpenURI::HTTPError, SocketError => e
|
28
38
|
puts "OpenURI: #{e.inspect}"
|
29
39
|
return nil
|
@@ -40,60 +50,63 @@ module Ficon
|
|
40
50
|
return nil
|
41
51
|
end
|
42
52
|
|
43
|
-
results = from_page(doc).collect {|result| normalise(uri, result) }.uniq
|
44
53
|
|
45
|
-
|
54
|
+
def process
|
55
|
+
@site.images = Site.site_images(@uri, doc)||[]
|
56
|
+
@site.page_images = Site.page_images(@uri, doc)||[]
|
57
|
+
other_page_data
|
58
|
+
end
|
46
59
|
|
47
|
-
|
48
|
-
|
60
|
+
def report
|
61
|
+
r = "Site icon: #{@site.images.first.to_s}\n"
|
62
|
+
r += "Page icon: #{@site.page_images.first.to_s}\n"
|
63
|
+
r += "Page title: #{@site.title}\n"
|
64
|
+
r += "Page description: #{@site.description}\n"
|
65
|
+
r += "Canonical URL: #{@site.canonical}\n"
|
49
66
|
|
50
|
-
|
51
|
-
|
52
|
-
# Check if root domain redirects before probing, striping path - eg http://www.apple.com.au/ -> http://www.apple.com/au/
|
67
|
+
return r
|
68
|
+
end
|
53
69
|
|
54
|
-
|
55
|
-
|
56
|
-
new_uri = URI(probe.header["Location"])
|
57
|
-
if ! new_uri.host.nil?
|
58
|
-
uri = new_uri
|
59
|
-
uri.path = ""
|
60
|
-
end
|
70
|
+
def site_icons
|
71
|
+
@site.images
|
61
72
|
end
|
62
73
|
|
63
|
-
|
64
|
-
|
74
|
+
def page_images
|
75
|
+
@site.page_images
|
76
|
+
end
|
65
77
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
78
|
+
def other_page_data
|
79
|
+
@site.title = doc.at_xpath("//meta[@property='og:title']/@content")&.value || @doc.at_xpath("//title")&.text&.strip
|
80
|
+
@site.description = doc.at_xpath("//meta[@property='og:description']/@content")&.value
|
81
|
+
canonical = doc.at_xpath("//link[@rel='canonical']/@href")&.value
|
82
|
+
@site.canonical = canonical unless canonical == @url
|
71
83
|
end
|
72
84
|
|
73
|
-
|
74
|
-
|
85
|
+
def self.site_images(uri, doc, site=nil)
|
86
|
+
results = []
|
75
87
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
elsif page.is_a? Nokogiri::HTML::Document
|
81
|
-
doc = page
|
82
|
-
else
|
83
|
-
raise ArgumentError
|
88
|
+
paths = "//meta[@name='msapplication-TileImage']|//link[@type='image/ico' or @type='image/vnd.microsoft.icon']|//link[@rel='icon' or @rel='shortcut icon' or @rel='apple-touch-icon-precomposed' or @rel='apple-touch-icon']"
|
89
|
+
results += doc.xpath(paths).collect {|e| e.values.select {|v| v =~ /\.png$|\.jpg$|\.gif$|\.ico$|\.svg$|\.ico\?\d*$/ }}.flatten.collect {|v| v[/^http/] || v[/^\//] ? v : '/' + v }
|
90
|
+
|
91
|
+
results = results.collect {|result| normalise(uri, result)}.uniq.collect {|i| Image.new(i) }.sort {|a,b| a.area <=> b.area }.reverse
|
84
92
|
end
|
85
93
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
94
|
+
def self.page_images(uri, doc, site=nil)
|
95
|
+
doc.xpath("//meta[@property='og:image']").
|
96
|
+
collect {|e| e.values.select {|v| v =~ /\.png$|\.jpg$|\.gif$|\.ico$|\.svg$|\.ico\?\d*$/ }}.flatten.
|
97
|
+
collect {|v| v[/^http/] || v[/^\//] ? v : '/' + v }.collect {|result| normalise(uri, result)}.uniq.collect {|i| Image.new(i)}.sort {|a, b| a.area <=> b.area }.reverse
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.normalise(base, candidate)
|
101
|
+
parsed_candidate = URI(candidate);
|
102
|
+
base = URI(base) unless base.is_a? URI
|
103
|
+
|
104
|
+
parsed_candidate.host = base.host if parsed_candidate.host.nil? # Set relative URLs to absolute
|
105
|
+
parsed_candidate.scheme = base.scheme if parsed_candidate.scheme.nil? # Set the schema if missing
|
106
|
+
|
107
|
+
parsed_candidate.to_s
|
108
|
+
end
|
90
109
|
|
91
|
-
def self.normalise(base, candidate)
|
92
|
-
parsed_candidate = URI(candidate);
|
93
|
-
|
94
|
-
parsed_candidate.host = base.host if parsed_candidate.host.nil? # Set relative URLs to absolute
|
95
|
-
parsed_candidate.scheme = base.scheme if parsed_candidate.scheme.nil? # Set the schema if missing
|
96
110
|
|
97
|
-
parsed_candidate.to_s
|
98
111
|
end
|
99
|
-
end
|
112
|
+
end
|
data/test/ficon_test.rb
CHANGED
@@ -1,41 +1,50 @@
|
|
1
|
-
require 'rubygems'
|
1
|
+
#require 'rubygems'
|
2
|
+
require 'byebug'
|
2
3
|
|
3
|
-
require
|
4
|
+
require "minitest/autorun"
|
4
5
|
|
5
6
|
PathHere = File.dirname(__FILE__)
|
6
7
|
$LOAD_PATH.unshift File.join(PathHere, "..", "lib")
|
7
8
|
|
8
9
|
require 'ficon'
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
Tests << { html: %Q{<link rel="shortcut icon" type="image/x-icon" href="/viconline/img/favicon.ico?1393375504" />}, value: '/viconline/img/favicon.ico?1393375504' }
|
11
|
+
SiteTests = []
|
12
|
+
SiteTests << { html: %Q{<meta name="msapplication-TileImage" content="https://s.yimg.com/pw/images/favicon-msapplication-tileimage.png"/> }, value: 'https://s.yimg.com/pw/images/favicon-msapplication-tileimage.png' }
|
13
|
+
SiteTests << { html: %Q{<link rel="shortcut icon" type="image/ico" href="https://s.yimg.com/pw/favicon.ico"> }, value: 'https://s.yimg.com/pw/favicon.ico' }
|
14
|
+
SiteTests << { html: %Q{<link href="/apple-touch-icon.png" rel="apple-touch-icon-precomposed">}, value: 'https://site.com/apple-touch-icon.png' }
|
15
|
+
SiteTests << { html: %Q{<link rel="shortcut icon" href="/wp-content/themes/torrentfreakredux/assets/img/icons/favicon.png">}, value: 'https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/favicon.png' }
|
16
|
+
SiteTests << { html: %Q{<link rel="apple-touch-icon-precomposed" href="/wp-content/themes/torrentfreakredux/assets/img/icons/57.png">}, value: 'https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/57.png' }
|
17
|
+
SiteTests << { html: %Q{<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/wp-content/themes/torrentfreakredux/assets/img/icons/114.png">}, value: 'https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/114.png' }
|
18
|
+
SiteTests << { html: %Q{<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/wp-content/themes/torrentfreakredux/assets/img/icons/72.png">}, value: 'https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/72.png' }
|
19
|
+
SiteTests << { html: %Q{<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/wp-content/themes/torrentfreakredux/assets/img/icons/144.png">}, value: 'https://site.com/wp-content/themes/torrentfreakredux/assets/img/icons/144.png' }
|
20
|
+
SiteTests << { html: %Q{<link rel="shortcut icon" href="/favicon.png">}, value: 'https://site.com/favicon.png' }
|
21
|
+
SiteTests << { html: %Q{<link rel="shortcut icon" href="favicon.ico" />}, value: 'https://site.com/favicon.ico' }
|
22
|
+
SiteTests << { html: %Q{<link rel="apple-touch-icon" href="/apple-touch-icon.png">}, value: 'https://site.com/apple-touch-icon.png' }
|
23
|
+
SiteTests << { html: %Q{<link rel="shortcut icon" href="http://example.com/myicon.ico" />}, value: 'http://example.com/myicon.ico'}
|
24
|
+
SiteTests << { html: %Q{<link rel="icon" href="http://example.com/image.ico" />}, value: 'http://example.com/image.ico' }
|
25
|
+
SiteTests << { html: %Q{<link rel="icon" type="image/vnd.microsoft.icon" href="http://example.com/image.ico" />}, value: 'http://example.com/image.ico' }
|
26
|
+
SiteTests << { html: %Q{<link rel="icon" type="image/png" href="http://example.com/image.png" />}, value: 'http://example.com/image.png' }
|
27
|
+
SiteTests << { html: %Q{<link rel="icon" type="image/gif" href="http://example.com/image.gif" />}, value: 'http://example.com/image.gif' }
|
28
|
+
SiteTests << { html: %Q{<link rel="icon" type="image/x-icon" href="http://example.com/image.ico"/>}, value: 'http://example.com/image.ico' }
|
29
|
+
SiteTests << { html: %Q{<link rel="shortcut icon" href="https://fbstatic-a.akamaihd.net/rsrc.php/yl/r/H3nktOa7ZMg.ico" />}, value: 'https://fbstatic-a.akamaihd.net/rsrc.php/yl/r/H3nktOa7ZMg.ico' }
|
30
|
+
SiteTests << { html: %Q{<link rel="icon" type="image/vnd.microsoft.icon" href="/viconline/img/favicon.ico?1393375504" />}, value: 'https://site.com/viconline/img/favicon.ico?1393375504' }
|
31
|
+
SiteTests << { html: %Q{<link rel="shortcut icon" type="image/x-icon" href="/viconline/img/favicon.ico?1393375504" />}, value: 'https://site.com/viconline/img/favicon.ico?1393375504' }
|
32
32
|
|
33
|
+
PageTests = []
|
34
|
+
PageTests << { html: %Q{<meta property="og:image" content="https://www.facebook.com/images/fb_icon_325x325.png" />}, value: 'https://www.facebook.com/images/fb_icon_325x325.png' }
|
33
35
|
|
34
|
-
|
36
|
+
|
37
|
+
class FiconTest < Minitest::Test
|
38
|
+
include Ficon
|
39
|
+
ENV['FICON_DB']=File.join( File.dirname(__FILE__), 'test.db')
|
35
40
|
def test_html_chunks
|
36
|
-
|
37
|
-
result =
|
38
|
-
assert result == t[:value], "Seaching |#{t[:html]}| expected #{t[:value]}, got #{result}"
|
41
|
+
SiteTests.each do |t|
|
42
|
+
result = Site.site_images('https://site.com', Nokogiri::HTML(t[:html]) )[0]
|
43
|
+
assert result&.url == t[:value], "Seaching |#{t[:html]}| expected #{t[:value]}, got #{result}"
|
44
|
+
end
|
45
|
+
PageTests.each do |t|
|
46
|
+
result = Site.page_images('https://site.com', Nokogiri::HTML(t[:html]) )[0]
|
47
|
+
assert result&.url == t[:value], "Seaching |#{t[:html]}| expected #{t[:value]}, got #{result}"
|
39
48
|
end
|
40
49
|
end
|
41
50
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ficon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Milne
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-04-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -16,42 +16,112 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.7'
|
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.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: addressable
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: fastimage
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sqlite3
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1'
|
27
69
|
- !ruby/object:Gem::Dependency
|
28
70
|
name: bundler
|
29
71
|
requirement: !ruby/object:Gem::Requirement
|
30
72
|
requirements:
|
31
73
|
- - "~>"
|
32
74
|
- !ruby/object:Gem::Version
|
33
|
-
version: '1
|
75
|
+
version: '1'
|
34
76
|
type: :development
|
35
77
|
prerelease: false
|
36
78
|
version_requirements: !ruby/object:Gem::Requirement
|
37
79
|
requirements:
|
38
80
|
- - "~>"
|
39
81
|
- !ruby/object:Gem::Version
|
40
|
-
version: '1
|
82
|
+
version: '1'
|
41
83
|
- !ruby/object:Gem::Dependency
|
42
84
|
name: rake
|
43
85
|
requirement: !ruby/object:Gem::Requirement
|
44
86
|
requirements:
|
45
87
|
- - "~>"
|
46
88
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
89
|
+
version: '12'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '12'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: minitest
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '5'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '5'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: byebug
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '9'
|
48
118
|
type: :development
|
49
119
|
prerelease: false
|
50
120
|
version_requirements: !ruby/object:Gem::Requirement
|
51
121
|
requirements:
|
52
122
|
- - "~>"
|
53
123
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
124
|
+
version: '9'
|
55
125
|
description: Ficon finds icons for websites and optionally, the best icon
|
56
126
|
email:
|
57
127
|
- d@nmilne.com
|
@@ -68,6 +138,8 @@ files:
|
|
68
138
|
- bin/ficon
|
69
139
|
- ficon.gemspec
|
70
140
|
- lib/ficon.rb
|
141
|
+
- lib/ficon/cache.rb
|
142
|
+
- lib/ficon/image.rb
|
71
143
|
- lib/ficon/version.rb
|
72
144
|
- test/ficon_test.rb
|
73
145
|
homepage: https://github.com/dkam/ficon
|
@@ -90,7 +162,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
90
162
|
version: '0'
|
91
163
|
requirements: []
|
92
164
|
rubyforge_project:
|
93
|
-
rubygems_version: 2.
|
165
|
+
rubygems_version: 2.6.11
|
94
166
|
signing_key:
|
95
167
|
specification_version: 4
|
96
168
|
summary: Find website icons
|