ficon 0.0.4 → 0.0.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f93ff5282fbdea68fba20fef8ec680122f0fc127
4
- data.tar.gz: 0501155e4a2b1cff104176f78e617ef3c5f13a3a
3
+ metadata.gz: d372436b5875c04a175f7756bef99aa917c6faef
4
+ data.tar.gz: 4a2909fa1f1eaf5cb3dd6e300381950c084704df
5
5
  SHA512:
6
- metadata.gz: d71449d493421e4f1068c263e74a8d5f4a6ee61b12dfe95977963e3e426737cf2a72b9edaff61ad6a1fb82f277cb53e388f14470775f623302fcc21ff9825b6d
7
- data.tar.gz: 44889ee60225766e370e6ab4ce1946a253bdfad07738cbcba2d56e1622907dee437054c23c8cc44a0b9013eeb7576d11316fb663e82934e25fb2507be48b6a59
6
+ metadata.gz: 5f451fb54ae264f32cb07d5d67fb9c4b4858b75a60347963cb9885c043dd330933e8fcb65aac058feb12de33f0851cbf5b8dbd64722cf25022a4dbfd42032aca
7
+ data.tar.gz: 5c5cb399f0c832270690dc220c0d8a9c13c00c99dc3d095acdb7d907eb3fb77df67d787228bf8906f2fcfcd763e07c9944d42ee49b335c33c2faad6cba18d791
data/bin/ficon CHANGED
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ $:.unshift File.join( File.dirname(__FILE__), "/../lib")
3
4
  require 'ficon'
5
+ include Ficon
4
6
 
5
- puts Ficon.from_uri ARGV[0]
7
+ puts Site.new(ARGV[0]).report
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.6"
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.6"
24
- spec.add_development_dependency "rake", "~> 10"
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
@@ -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
+
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Ficon
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
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 'net/http'
4
+ require "ostruct"
5
+ require 'addressable/uri'
6
+ require 'byebug'
7
7
 
8
- module Ficon
9
- def self.from_uri(_uri)
8
+ require_relative 'ficon/version'
9
+ require_relative 'ficon/image'
10
+ require_relative 'ficon/cache'
10
11
 
11
- uri = nil
12
- doc = nil
12
+ module Ficon
13
+ class Site
13
14
 
14
- begin
15
- require 'addressable/uri'
16
- uri = Addressable::URI.heuristic_parse(_uri)
17
- rescue LoadError
18
- uri = URI(_uri)
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
- begin
22
- data = open(uri)
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
- results.concat( from_probes(uri, results) )
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
- return results
48
- end
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
- def self.from_probes(uri, already_found=[])
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
- probe = Net::HTTP.new(uri.host).request_head("/")
55
- if probe.code == "301" || probe.code == "302"
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
- results = []
64
- guesses = ["/favicon.ico", "/favicon.png"]
74
+ def page_images
75
+ @site.page_images
76
+ end
65
77
 
66
- guesses.each do |guess|
67
- uri.path = guess
68
- unless already_found.include?( uri.to_s )
69
- results << uri.to_s if( Net::HTTP.new(uri.host).request_head(uri.path).header.code == "200")
70
- end
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
- return results
74
- end
85
+ def self.site_images(uri, doc, site=nil)
86
+ results = []
75
87
 
76
- def self.from_page(page)
77
- doc = nil
78
- if page.is_a? String
79
- doc = Nokogiri::HTML(page)
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
- doc.xpath("//meta[@property='og:image']|//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']").
87
- collect {|e| e.values.select {|v| v =~ /\.png$|\.jpg$|\.gif$|\.ico$|\.svg$|\.ico\?\d*$/ }}.flatten.
88
- collect {|v| v[/^http/] || v[/^\//] ? v : '/' + v }
89
- end
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 'test/unit'
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
- Tests = []
11
- Tests << { 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' }
12
- Tests << { 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' }
13
- Tests << { html: %Q{<link href="/apple-touch-icon.png" rel="apple-touch-icon-precomposed">}, value: '/apple-touch-icon.png' }
14
- Tests << { html: %Q{<link rel="shortcut icon" href="/wp-content/themes/torrentfreakredux/assets/img/icons/favicon.png">}, value: '/wp-content/themes/torrentfreakredux/assets/img/icons/favicon.png' }
15
- Tests << { html: %Q{<link rel="apple-touch-icon-precomposed" href="/wp-content/themes/torrentfreakredux/assets/img/icons/57.png">}, value: '/wp-content/themes/torrentfreakredux/assets/img/icons/57.png' }
16
- Tests << { html: %Q{<link rel="apple-touch-icon-precomposed" sizes="114x114" href="/wp-content/themes/torrentfreakredux/assets/img/icons/114.png">}, value: '/wp-content/themes/torrentfreakredux/assets/img/icons/114.png' }
17
- Tests << { html: %Q{<link rel="apple-touch-icon-precomposed" sizes="72x72" href="/wp-content/themes/torrentfreakredux/assets/img/icons/72.png">}, value: '/wp-content/themes/torrentfreakredux/assets/img/icons/72.png' }
18
- Tests << { html: %Q{<link rel="apple-touch-icon-precomposed" sizes="144x144" href="/wp-content/themes/torrentfreakredux/assets/img/icons/144.png">}, value: '/wp-content/themes/torrentfreakredux/assets/img/icons/144.png' }
19
- Tests << { html: %Q{<link rel="shortcut icon" href="/favicon.png">}, value: '/favicon.png' }
20
- Tests << { html: %Q{<link rel="shortcut icon" href="favicon.ico" />}, value: '/favicon.ico' }
21
- Tests << { html: %Q{<link rel="apple-touch-icon" href="/apple-touch-icon.png">}, value: '/apple-touch-icon.png' }
22
- Tests << { html: %Q{<link rel="shortcut icon" href="http://example.com/myicon.ico" />}, value: 'http://example.com/myicon.ico'}
23
- Tests << { html: %Q{<link rel="icon" href="http://example.com/image.ico" />}, value: 'http://example.com/image.ico' }
24
- Tests << { html: %Q{<link rel="icon" type="image/vnd.microsoft.icon" href="http://example.com/image.ico" />}, value: 'http://example.com/image.ico' }
25
- Tests << { html: %Q{<link rel="icon" type="image/png" href="http://example.com/image.png" />}, value: 'http://example.com/image.png' }
26
- Tests << { html: %Q{<link rel="icon" type="image/gif" href="http://example.com/image.gif" />}, value: 'http://example.com/image.gif' }
27
- Tests << { html: %Q{<link rel="icon" type="image/x-icon" href="http://example.com/image.ico"/>}, value: 'http://example.com/image.ico' }
28
- Tests << { 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' }
29
- Tests << { 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' }
30
- Tests << { html: %Q{<link rel="icon" type="image/vnd.microsoft.icon" href="/viconline/img/favicon.ico?1393375504" />}, value: '/viconline/img/favicon.ico?1393375504' }
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
- class FiconTest < Test::Unit::TestCase
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
- Tests.each do |t|
37
- result = Ficon.from_page( t[:html] )[0]
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
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: 2014-12-08 00:00:00.000000000 Z
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.6'
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.6'
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.6'
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.6'
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: '10'
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: '10'
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.2.2
165
+ rubygems_version: 2.6.11
94
166
  signing_key:
95
167
  specification_version: 4
96
168
  summary: Find website icons