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