link_thumbnailer 1.1.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/.travis.yml +1 -1
- data/CHANGELOG.md +117 -104
- data/Gemfile +1 -1
- data/{LICENSE → LICENSE.txt} +21 -21
- data/README.md +153 -184
- data/lib/generators/link_thumbnailer/install_generator.rb +0 -4
- data/lib/generators/templates/initializer.rb +63 -41
- data/lib/link_thumbnailer/configuration.rb +52 -10
- data/lib/link_thumbnailer/exceptions.rb +6 -0
- data/lib/link_thumbnailer/grader.rb +37 -0
- data/lib/link_thumbnailer/graders/base.rb +32 -0
- data/lib/link_thumbnailer/graders/html_attribute.rb +49 -0
- data/lib/link_thumbnailer/graders/length.rb +19 -0
- data/lib/link_thumbnailer/graders/link_density.rb +21 -0
- data/lib/link_thumbnailer/graders/position.rb +11 -0
- data/lib/link_thumbnailer/image_comparator.rb +24 -0
- data/lib/link_thumbnailer/image_comparators/base.rb +17 -0
- data/lib/link_thumbnailer/image_comparators/size.rb +11 -0
- data/lib/link_thumbnailer/image_parser.rb +18 -0
- data/lib/link_thumbnailer/image_parsers/size.rb +15 -0
- data/lib/link_thumbnailer/image_parsers/type.rb +15 -0
- data/lib/link_thumbnailer/image_validator.rb +30 -0
- data/lib/link_thumbnailer/model.rb +16 -0
- data/lib/link_thumbnailer/models/description.rb +34 -0
- data/lib/link_thumbnailer/models/image.rb +54 -0
- data/lib/link_thumbnailer/models/title.rb +20 -0
- data/lib/link_thumbnailer/models/website.rb +39 -0
- data/lib/link_thumbnailer/page.rb +40 -0
- data/lib/link_thumbnailer/parser.rb +13 -0
- data/lib/link_thumbnailer/processor.rb +94 -0
- data/lib/link_thumbnailer/railtie.rb +9 -9
- data/lib/link_thumbnailer/scraper.rb +64 -0
- data/lib/link_thumbnailer/scrapers/base.rb +63 -0
- data/lib/link_thumbnailer/scrapers/default/base.rb +10 -0
- data/lib/link_thumbnailer/scrapers/default/description.rb +47 -0
- data/lib/link_thumbnailer/scrapers/default/images.rb +64 -0
- data/lib/link_thumbnailer/scrapers/default/title.rb +25 -0
- data/lib/link_thumbnailer/scrapers/opengraph/base.rb +43 -0
- data/lib/link_thumbnailer/scrapers/opengraph/description.rb +10 -0
- data/lib/link_thumbnailer/scrapers/opengraph/image.rb +30 -0
- data/lib/link_thumbnailer/scrapers/opengraph/images.rb +16 -0
- data/lib/link_thumbnailer/scrapers/opengraph/title.rb +10 -0
- data/lib/link_thumbnailer/version.rb +3 -3
- data/lib/link_thumbnailer.rb +36 -119
- data/link_thumbnailer.gemspec +26 -28
- data/spec/configuration_spec.rb +51 -0
- data/spec/examples/empty_og_image_example.html +9 -0
- data/spec/fixture_spec.rb +88 -0
- data/spec/fixtures/bar.png +2907 -0
- data/spec/fixtures/default_from_body.html +12 -0
- data/spec/fixtures/default_from_meta.html +11 -0
- data/spec/{examples → fixtures}/example.html +53 -53
- data/spec/fixtures/foo.png +0 -0
- data/spec/fixtures/og_not_valid_example.html +12 -0
- data/spec/fixtures/og_valid_example.html +12 -0
- data/spec/fixtures/og_valid_multi_image_example.html +13 -0
- data/spec/grader_spec.rb +24 -0
- data/spec/graders/base_spec.rb +12 -0
- data/spec/graders/html_attribute_spec.rb +48 -0
- data/spec/graders/length_spec.rb +81 -0
- data/spec/graders/link_density_spec.rb +22 -0
- data/spec/image_comparators/size_spec.rb +39 -0
- data/spec/image_parsers/size_spec.rb +34 -0
- data/spec/image_parsers/type_spec.rb +34 -0
- data/spec/image_validator_spec.rb +35 -0
- data/spec/model_spec.rb +17 -0
- data/spec/models/description_spec.rb +64 -0
- data/spec/models/image_spec.rb +71 -0
- data/spec/models/title_spec.rb +24 -0
- data/spec/models/website_spec.rb +49 -0
- data/spec/page_spec.rb +26 -0
- data/spec/processor_spec.rb +349 -0
- data/spec/scraper_spec.rb +95 -0
- data/spec/scrapers/base_spec.rb +67 -0
- data/spec/scrapers/opengraph/base_spec.rb +94 -0
- data/spec/spec_helper.rb +15 -13
- metadata +126 -120
- data/app/controllers/link_thumbnailer/application_controller.rb +0 -4
- data/app/controllers/link_thumbnailer/previews_controller.rb +0 -11
- data/lib/link_thumbnailer/doc.rb +0 -65
- data/lib/link_thumbnailer/doc_parser.rb +0 -15
- data/lib/link_thumbnailer/engine.rb +0 -4
- data/lib/link_thumbnailer/fetcher.rb +0 -34
- data/lib/link_thumbnailer/img_comparator.rb +0 -17
- data/lib/link_thumbnailer/img_parser.rb +0 -41
- data/lib/link_thumbnailer/img_url_filter.rb +0 -13
- data/lib/link_thumbnailer/object.rb +0 -41
- data/lib/link_thumbnailer/opengraph.rb +0 -20
- data/lib/link_thumbnailer/rails/routes/mapper.rb +0 -30
- data/lib/link_thumbnailer/rails/routes/mapping.rb +0 -33
- data/lib/link_thumbnailer/rails/routes.rb +0 -47
- data/lib/link_thumbnailer/web_image.rb +0 -19
- data/spec/doc_parser_spec.rb +0 -25
- data/spec/doc_spec.rb +0 -23
- data/spec/examples/empty_example.html +0 -11
- data/spec/examples/og_example.html +0 -12
- data/spec/fetcher_spec.rb +0 -97
- data/spec/img_comparator_spec.rb +0 -16
- data/spec/img_url_filter_spec.rb +0 -31
- data/spec/link_thumbnailer_spec.rb +0 -205
- data/spec/object_spec.rb +0 -130
- data/spec/opengraph_spec.rb +0 -7
- data/spec/web_image_spec.rb +0 -57
@@ -1,41 +1,63 @@
|
|
1
|
-
# Use this hook to configure LinkThumbnailer bahaviors.
|
2
|
-
LinkThumbnailer.configure do |config|
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# config.
|
6
|
-
|
7
|
-
#
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
|
13
|
-
#
|
14
|
-
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
|
21
|
-
#
|
22
|
-
|
23
|
-
#
|
24
|
-
#
|
25
|
-
# config.
|
26
|
-
|
27
|
-
#
|
28
|
-
#
|
29
|
-
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
#
|
34
|
-
# config.
|
35
|
-
|
36
|
-
#
|
37
|
-
#
|
38
|
-
|
39
|
-
#
|
40
|
-
# config.
|
41
|
-
|
1
|
+
# Use this hook to configure LinkThumbnailer bahaviors.
|
2
|
+
LinkThumbnailer.configure do |config|
|
3
|
+
# Numbers of redirects before raising an exception when trying to parse given url.
|
4
|
+
#
|
5
|
+
# config.redirect_limit = 3
|
6
|
+
|
7
|
+
# Set user agent
|
8
|
+
#
|
9
|
+
# config.user_agent = 'link_thumbnailer'
|
10
|
+
|
11
|
+
# Enable or disable SSL verification
|
12
|
+
#
|
13
|
+
# config.verify_ssl = true
|
14
|
+
|
15
|
+
# The amount of time in seconds to wait for a connection to be opened.
|
16
|
+
# If the HTTP object cannot open a connection in this many seconds,
|
17
|
+
# it raises a Net::OpenTimeout exception.
|
18
|
+
#
|
19
|
+
# See http://www.ruby-doc.org/stdlib-2.1.1/libdoc/net/http/rdoc/Net/HTTP.html#open_timeout
|
20
|
+
#
|
21
|
+
# config.http_timeout = 5
|
22
|
+
|
23
|
+
# List of blacklisted urls you want to skip when searching for images.
|
24
|
+
#
|
25
|
+
# config.blacklist_urls = [
|
26
|
+
# %r{^http://ad\.doubleclick\.net/},
|
27
|
+
# %r{^http://b\.scorecardresearch\.com/},
|
28
|
+
# %r{^http://pixel\.quantserve\.com/},
|
29
|
+
# %r{^http://s7\.addthis\.com/}
|
30
|
+
# ]
|
31
|
+
|
32
|
+
# List of attributes you want LinkThumbnailer to fetch on a website.
|
33
|
+
#
|
34
|
+
# config.attributes = [:title, :images, :description]
|
35
|
+
|
36
|
+
# List of procedures used to rate the website description. Add you custom class
|
37
|
+
# here. Note that the order matter to compute the score. See wiki for more details
|
38
|
+
# on how to build your own graders.
|
39
|
+
#
|
40
|
+
# config.graders = [
|
41
|
+
# ->(description) { ::LinkThumbnailer::Graders::Length.new(description) },
|
42
|
+
# ->(description) { ::LinkThumbnailer::Graders::HtmlAttribute.new(description, :class) },
|
43
|
+
# ->(description) { ::LinkThumbnailer::Graders::HtmlAttribute.new(description, :id) },
|
44
|
+
# ->(description) { ::LinkThumbnailer::Graders::Position.new(description) },
|
45
|
+
# ->(description) { ::LinkThumbnailer::Graders::LinkDensity.new(description) }
|
46
|
+
# ]
|
47
|
+
|
48
|
+
# Minimum description length for a website.
|
49
|
+
#
|
50
|
+
# config.description_min_length = 25
|
51
|
+
|
52
|
+
# Regex of words considered positive to rate website description.
|
53
|
+
#
|
54
|
+
# config.positive_regex = /article|body|content|entry|hentry|main|page|pagination|post|text|blog|story/i
|
55
|
+
|
56
|
+
# Regex of words considered negative to rate website description.
|
57
|
+
#
|
58
|
+
# config.negative_regex = /combx|comment|com-|contact|foot|footer|footnote|masthead|media|meta|outbrain|promo|related|scroll|shoutbox|sidebar|sponsor|shopping|tags|tool|widget|modal/i
|
59
|
+
|
60
|
+
# Numbers of images to fetch. Fetching too many images will be slow.
|
61
|
+
#
|
62
|
+
# config.image_limit = 5
|
63
|
+
end
|
@@ -1,16 +1,58 @@
|
|
1
|
-
require 'hashie'
|
2
|
-
|
3
1
|
module LinkThumbnailer
|
4
|
-
class Configuration < Hashie::Mash
|
5
2
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
# Access point for the gem configurations.
|
4
|
+
#
|
5
|
+
# @return [LinkThumbnailer::Configuration] a configuration instance.
|
6
|
+
def self.config
|
7
|
+
@config ||= Configuration.new
|
8
|
+
end
|
9
|
+
|
10
|
+
# Configure hook used in the gem initializer. Convinient way to set all the
|
11
|
+
# gem configurations.
|
12
|
+
#
|
13
|
+
# @example inside config/initializers/link_thumbnaler.rb
|
14
|
+
# LinkThumbnailer.configure do |config|
|
15
|
+
# config.user_agent = 'link_thumbnailer'
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# @return [void]
|
19
|
+
def self.configure
|
20
|
+
yield config if block_given?
|
21
|
+
end
|
22
|
+
|
23
|
+
class Configuration
|
24
|
+
|
25
|
+
attr_accessor :redirect_limit, :blacklist_urls, :user_agent,
|
26
|
+
:verify_ssl, :http_timeout, :attributes, :graders,
|
27
|
+
:description_min_length, :positive_regex, :negative_regex,
|
28
|
+
:image_limit
|
10
29
|
|
11
|
-
|
12
|
-
|
13
|
-
|
30
|
+
# Create a new instance.
|
31
|
+
#
|
32
|
+
# @return [LinkThumbnailer::Configuration]
|
33
|
+
def initialize
|
34
|
+
@redirect_limit = 3
|
35
|
+
@user_agent = 'link_thumbnailer'
|
36
|
+
@verify_ssl = true
|
37
|
+
@http_timeout = 5
|
38
|
+
@blacklist_urls = [
|
39
|
+
%r{^http://ad\.doubleclick\.net/},
|
40
|
+
%r{^http://b\.scorecardresearch\.com/},
|
41
|
+
%r{^http://pixel\.quantserve\.com/},
|
42
|
+
%r{^http://s7\.addthis\.com/}
|
43
|
+
]
|
44
|
+
@attributes = [:title, :images, :description]
|
45
|
+
@graders = [
|
46
|
+
->(description) { ::LinkThumbnailer::Graders::Length.new(description) },
|
47
|
+
->(description) { ::LinkThumbnailer::Graders::HtmlAttribute.new(description, :class) },
|
48
|
+
->(description) { ::LinkThumbnailer::Graders::HtmlAttribute.new(description, :id) },
|
49
|
+
->(description) { ::LinkThumbnailer::Graders::Position.new(description) },
|
50
|
+
->(description) { ::LinkThumbnailer::Graders::LinkDensity.new(description) }
|
51
|
+
]
|
52
|
+
@description_min_length = 25
|
53
|
+
@positive_regex = /article|body|content|entry|hentry|main|page|pagination|post|text|blog|story/i
|
54
|
+
@negative_regex = /combx|comment|com-|contact|foot|footer|footnote|masthead|media|meta|outbrain|promo|related|scroll|shoutbox|sidebar|sponsor|shopping|tags|tool|widget|modal/i
|
55
|
+
@image_limit = 5
|
14
56
|
end
|
15
57
|
|
16
58
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
require 'link_thumbnailer/graders/base'
|
3
|
+
require 'link_thumbnailer/graders/length'
|
4
|
+
require 'link_thumbnailer/graders/html_attribute'
|
5
|
+
require 'link_thumbnailer/graders/link_density'
|
6
|
+
require 'link_thumbnailer/graders/position'
|
7
|
+
|
8
|
+
module LinkThumbnailer
|
9
|
+
class Grader < ::SimpleDelegator
|
10
|
+
|
11
|
+
attr_reader :config, :description
|
12
|
+
|
13
|
+
def initialize(description)
|
14
|
+
@config = ::LinkThumbnailer.page.config
|
15
|
+
@description = description
|
16
|
+
|
17
|
+
super(config)
|
18
|
+
end
|
19
|
+
|
20
|
+
def call
|
21
|
+
score = 0
|
22
|
+
graders.each do |lambda|
|
23
|
+
instance = lambda.call(description)
|
24
|
+
score += instance.call(score)
|
25
|
+
end
|
26
|
+
|
27
|
+
score
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def graders
|
33
|
+
config.graders
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module LinkThumbnailer
|
4
|
+
module Graders
|
5
|
+
class Base < ::SimpleDelegator
|
6
|
+
|
7
|
+
attr_reader :config, :description
|
8
|
+
|
9
|
+
def initialize(description)
|
10
|
+
@config = ::LinkThumbnailer.page.config
|
11
|
+
@description = description
|
12
|
+
|
13
|
+
super(config)
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(current_score)
|
17
|
+
raise 'must implement'
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def node
|
23
|
+
description.node
|
24
|
+
end
|
25
|
+
|
26
|
+
def text
|
27
|
+
node.text
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module LinkThumbnailer
|
2
|
+
module Graders
|
3
|
+
class HtmlAttribute < ::LinkThumbnailer::Graders::Base
|
4
|
+
|
5
|
+
attr_reader :attribute_name
|
6
|
+
|
7
|
+
def initialize(description, attribute_name)
|
8
|
+
super(description)
|
9
|
+
@attribute_name = attribute_name.to_sym
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(current_score)
|
13
|
+
return 0 unless attribute?
|
14
|
+
|
15
|
+
score = 0
|
16
|
+
score -= 25 if negative?
|
17
|
+
score += 25 if positive?
|
18
|
+
score
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def attribute
|
24
|
+
node[attribute_name]
|
25
|
+
end
|
26
|
+
|
27
|
+
def attribute?
|
28
|
+
attribute && !attribute.empty?
|
29
|
+
end
|
30
|
+
|
31
|
+
def negative?
|
32
|
+
attribute =~ negative_regex
|
33
|
+
end
|
34
|
+
|
35
|
+
def positive?
|
36
|
+
attribute =~ positive_regex
|
37
|
+
end
|
38
|
+
|
39
|
+
def negative_regex
|
40
|
+
config.negative_regex
|
41
|
+
end
|
42
|
+
|
43
|
+
def positive_regex
|
44
|
+
config.positive_regex
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module LinkThumbnailer
|
2
|
+
module Graders
|
3
|
+
class Length < ::LinkThumbnailer::Graders::Base
|
4
|
+
|
5
|
+
def call(current_score)
|
6
|
+
return -Float::INFINITY if too_short?
|
7
|
+
|
8
|
+
[(text.length / 100).to_i, 3].min
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def too_short?
|
14
|
+
text.length < config.description_min_length
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module LinkThumbnailer
|
2
|
+
module Graders
|
3
|
+
class LinkDensity < ::LinkThumbnailer::Graders::Base
|
4
|
+
|
5
|
+
def call(current_score)
|
6
|
+
current_score *= (1 - density)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def density
|
12
|
+
links.length / text.length.to_f
|
13
|
+
end
|
14
|
+
|
15
|
+
def links
|
16
|
+
node.css('a').map(&:text)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'link_thumbnailer/image_comparators/base'
|
2
|
+
require 'link_thumbnailer/image_comparators/size'
|
3
|
+
|
4
|
+
module LinkThumbnailer
|
5
|
+
class ImageComparator
|
6
|
+
|
7
|
+
attr_reader :image
|
8
|
+
|
9
|
+
def initialize(image)
|
10
|
+
@image = image
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(other)
|
14
|
+
size_comparator.call(other)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def size_comparator
|
20
|
+
::LinkThumbnailer::ImageComparators::Size.new(image)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'link_thumbnailer/image_parsers/size'
|
2
|
+
require 'link_thumbnailer/image_parsers/type'
|
3
|
+
|
4
|
+
module LinkThumbnailer
|
5
|
+
class ImageParser
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def size(image)
|
9
|
+
::LinkThumbnailer::ImageParsers::Size.perform(image)
|
10
|
+
end
|
11
|
+
|
12
|
+
def type(image)
|
13
|
+
::LinkThumbnailer::ImageParsers::Type.perform(image)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module LinkThumbnailer
|
4
|
+
class ImageValidator < ::SimpleDelegator
|
5
|
+
|
6
|
+
attr_reader :config, :image
|
7
|
+
|
8
|
+
def initialize(image)
|
9
|
+
@config = ::LinkThumbnailer.page.config
|
10
|
+
@image = image
|
11
|
+
|
12
|
+
super(config)
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
blacklist_urls.each do |url|
|
17
|
+
return false if image.src && image.src.to_s[url]
|
18
|
+
end
|
19
|
+
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def blacklist_urls
|
26
|
+
config.blacklist_urls
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'link_thumbnailer/model'
|
2
|
+
require 'link_thumbnailer/grader'
|
3
|
+
|
4
|
+
module LinkThumbnailer
|
5
|
+
module Models
|
6
|
+
class Description < ::LinkThumbnailer::Model
|
7
|
+
|
8
|
+
attr_reader :node, :text, :position
|
9
|
+
attr_accessor :score
|
10
|
+
|
11
|
+
def initialize(node, text, position = 1)
|
12
|
+
@node = node
|
13
|
+
@text = sanitize(text)
|
14
|
+
@position = position
|
15
|
+
@score = compute_score
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
text
|
20
|
+
end
|
21
|
+
|
22
|
+
def <=>(other)
|
23
|
+
score <=> other.score
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def compute_score
|
29
|
+
::LinkThumbnailer::Grader.new(self).call
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'link_thumbnailer/model'
|
2
|
+
require 'link_thumbnailer/image_parser'
|
3
|
+
require 'link_thumbnailer/image_comparator'
|
4
|
+
require 'link_thumbnailer/image_validator'
|
5
|
+
|
6
|
+
module LinkThumbnailer
|
7
|
+
module Models
|
8
|
+
class Image < ::LinkThumbnailer::Model
|
9
|
+
|
10
|
+
attr_reader :src, :type, :size
|
11
|
+
|
12
|
+
def initialize(src)
|
13
|
+
@src = src
|
14
|
+
@size = parser.size(self)
|
15
|
+
@type = parser.type(self)
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
src.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
def <=>(other)
|
23
|
+
comparator.call(other)
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid?
|
27
|
+
validator.call
|
28
|
+
end
|
29
|
+
|
30
|
+
def as_json(*)
|
31
|
+
{
|
32
|
+
src: src.to_s,
|
33
|
+
size: size,
|
34
|
+
type: type
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def parser
|
41
|
+
::LinkThumbnailer::ImageParser
|
42
|
+
end
|
43
|
+
|
44
|
+
def validator
|
45
|
+
::LinkThumbnailer::ImageValidator.new(self)
|
46
|
+
end
|
47
|
+
|
48
|
+
def comparator
|
49
|
+
::LinkThumbnailer::ImageComparator.new(self)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'link_thumbnailer/model'
|
2
|
+
|
3
|
+
module LinkThumbnailer
|
4
|
+
module Models
|
5
|
+
class Title < ::LinkThumbnailer::Model
|
6
|
+
|
7
|
+
attr_reader :node, :text
|
8
|
+
|
9
|
+
def initialize(node, text = nil)
|
10
|
+
@node = node
|
11
|
+
@text = sanitize(text || node.text)
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
text
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'link_thumbnailer/model'
|
2
|
+
|
3
|
+
module LinkThumbnailer
|
4
|
+
module Models
|
5
|
+
class Website < ::LinkThumbnailer::Model
|
6
|
+
|
7
|
+
attr_accessor :url, :title, :description, :images
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@images = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def image=(image)
|
14
|
+
self.images = image
|
15
|
+
end
|
16
|
+
|
17
|
+
def images=(images)
|
18
|
+
Array(images).each do |image|
|
19
|
+
next unless image.valid?
|
20
|
+
@images << image
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def images
|
25
|
+
@images.sort!
|
26
|
+
end
|
27
|
+
|
28
|
+
def as_json(*)
|
29
|
+
{
|
30
|
+
url: url.to_s,
|
31
|
+
title: title,
|
32
|
+
description: description,
|
33
|
+
images: images
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|