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 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