link_thumbnailer 1.1.2 → 2.0.0

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.
Files changed (104) hide show
  1. checksums.yaml +5 -13
  2. data/.travis.yml +1 -1
  3. data/CHANGELOG.md +117 -104
  4. data/Gemfile +1 -1
  5. data/{LICENSE → LICENSE.txt} +21 -21
  6. data/README.md +153 -184
  7. data/lib/generators/link_thumbnailer/install_generator.rb +0 -4
  8. data/lib/generators/templates/initializer.rb +63 -41
  9. data/lib/link_thumbnailer/configuration.rb +52 -10
  10. data/lib/link_thumbnailer/exceptions.rb +6 -0
  11. data/lib/link_thumbnailer/grader.rb +37 -0
  12. data/lib/link_thumbnailer/graders/base.rb +32 -0
  13. data/lib/link_thumbnailer/graders/html_attribute.rb +49 -0
  14. data/lib/link_thumbnailer/graders/length.rb +19 -0
  15. data/lib/link_thumbnailer/graders/link_density.rb +21 -0
  16. data/lib/link_thumbnailer/graders/position.rb +11 -0
  17. data/lib/link_thumbnailer/image_comparator.rb +24 -0
  18. data/lib/link_thumbnailer/image_comparators/base.rb +17 -0
  19. data/lib/link_thumbnailer/image_comparators/size.rb +11 -0
  20. data/lib/link_thumbnailer/image_parser.rb +18 -0
  21. data/lib/link_thumbnailer/image_parsers/size.rb +15 -0
  22. data/lib/link_thumbnailer/image_parsers/type.rb +15 -0
  23. data/lib/link_thumbnailer/image_validator.rb +30 -0
  24. data/lib/link_thumbnailer/model.rb +16 -0
  25. data/lib/link_thumbnailer/models/description.rb +34 -0
  26. data/lib/link_thumbnailer/models/image.rb +54 -0
  27. data/lib/link_thumbnailer/models/title.rb +20 -0
  28. data/lib/link_thumbnailer/models/website.rb +39 -0
  29. data/lib/link_thumbnailer/page.rb +40 -0
  30. data/lib/link_thumbnailer/parser.rb +13 -0
  31. data/lib/link_thumbnailer/processor.rb +94 -0
  32. data/lib/link_thumbnailer/railtie.rb +9 -9
  33. data/lib/link_thumbnailer/scraper.rb +64 -0
  34. data/lib/link_thumbnailer/scrapers/base.rb +63 -0
  35. data/lib/link_thumbnailer/scrapers/default/base.rb +10 -0
  36. data/lib/link_thumbnailer/scrapers/default/description.rb +47 -0
  37. data/lib/link_thumbnailer/scrapers/default/images.rb +64 -0
  38. data/lib/link_thumbnailer/scrapers/default/title.rb +25 -0
  39. data/lib/link_thumbnailer/scrapers/opengraph/base.rb +43 -0
  40. data/lib/link_thumbnailer/scrapers/opengraph/description.rb +10 -0
  41. data/lib/link_thumbnailer/scrapers/opengraph/image.rb +30 -0
  42. data/lib/link_thumbnailer/scrapers/opengraph/images.rb +16 -0
  43. data/lib/link_thumbnailer/scrapers/opengraph/title.rb +10 -0
  44. data/lib/link_thumbnailer/version.rb +3 -3
  45. data/lib/link_thumbnailer.rb +36 -119
  46. data/link_thumbnailer.gemspec +26 -28
  47. data/spec/configuration_spec.rb +51 -0
  48. data/spec/examples/empty_og_image_example.html +9 -0
  49. data/spec/fixture_spec.rb +88 -0
  50. data/spec/fixtures/bar.png +2907 -0
  51. data/spec/fixtures/default_from_body.html +12 -0
  52. data/spec/fixtures/default_from_meta.html +11 -0
  53. data/spec/{examples → fixtures}/example.html +53 -53
  54. data/spec/fixtures/foo.png +0 -0
  55. data/spec/fixtures/og_not_valid_example.html +12 -0
  56. data/spec/fixtures/og_valid_example.html +12 -0
  57. data/spec/fixtures/og_valid_multi_image_example.html +13 -0
  58. data/spec/grader_spec.rb +24 -0
  59. data/spec/graders/base_spec.rb +12 -0
  60. data/spec/graders/html_attribute_spec.rb +48 -0
  61. data/spec/graders/length_spec.rb +81 -0
  62. data/spec/graders/link_density_spec.rb +22 -0
  63. data/spec/image_comparators/size_spec.rb +39 -0
  64. data/spec/image_parsers/size_spec.rb +34 -0
  65. data/spec/image_parsers/type_spec.rb +34 -0
  66. data/spec/image_validator_spec.rb +35 -0
  67. data/spec/model_spec.rb +17 -0
  68. data/spec/models/description_spec.rb +64 -0
  69. data/spec/models/image_spec.rb +71 -0
  70. data/spec/models/title_spec.rb +24 -0
  71. data/spec/models/website_spec.rb +49 -0
  72. data/spec/page_spec.rb +26 -0
  73. data/spec/processor_spec.rb +349 -0
  74. data/spec/scraper_spec.rb +95 -0
  75. data/spec/scrapers/base_spec.rb +67 -0
  76. data/spec/scrapers/opengraph/base_spec.rb +94 -0
  77. data/spec/spec_helper.rb +15 -13
  78. metadata +126 -120
  79. data/app/controllers/link_thumbnailer/application_controller.rb +0 -4
  80. data/app/controllers/link_thumbnailer/previews_controller.rb +0 -11
  81. data/lib/link_thumbnailer/doc.rb +0 -65
  82. data/lib/link_thumbnailer/doc_parser.rb +0 -15
  83. data/lib/link_thumbnailer/engine.rb +0 -4
  84. data/lib/link_thumbnailer/fetcher.rb +0 -34
  85. data/lib/link_thumbnailer/img_comparator.rb +0 -17
  86. data/lib/link_thumbnailer/img_parser.rb +0 -41
  87. data/lib/link_thumbnailer/img_url_filter.rb +0 -13
  88. data/lib/link_thumbnailer/object.rb +0 -41
  89. data/lib/link_thumbnailer/opengraph.rb +0 -20
  90. data/lib/link_thumbnailer/rails/routes/mapper.rb +0 -30
  91. data/lib/link_thumbnailer/rails/routes/mapping.rb +0 -33
  92. data/lib/link_thumbnailer/rails/routes.rb +0 -47
  93. data/lib/link_thumbnailer/web_image.rb +0 -19
  94. data/spec/doc_parser_spec.rb +0 -25
  95. data/spec/doc_spec.rb +0 -23
  96. data/spec/examples/empty_example.html +0 -11
  97. data/spec/examples/og_example.html +0 -12
  98. data/spec/fetcher_spec.rb +0 -97
  99. data/spec/img_comparator_spec.rb +0 -16
  100. data/spec/img_url_filter_spec.rb +0 -31
  101. data/spec/link_thumbnailer_spec.rb +0 -205
  102. data/spec/object_spec.rb +0 -130
  103. data/spec/opengraph_spec.rb +0 -7
  104. data/spec/web_image_spec.rb +0 -57
@@ -6,10 +6,6 @@ module LinkThumbnailer
6
6
 
7
7
  desc 'Creates a LinkThumbnailer initializer for your application.'
8
8
 
9
- def install
10
- route "use_link_thumbnailer"
11
- end
12
-
13
9
  def copy_initializer
14
10
  template 'initializer.rb', 'config/initializers/link_thumbnailer.rb'
15
11
  end
@@ -1,41 +1,63 @@
1
- # Use this hook to configure LinkThumbnailer bahaviors.
2
- LinkThumbnailer.configure do |config|
3
- # Set mandatory attributes require for the website to be valid.
4
- # You can set `strict` to false if you want to skip this validation.
5
- # config.mandatory_attributes = %w(url title image)
6
-
7
- # Whether you want to validate given website against mandatory attributes or not.
8
- # config.strict = true
9
-
10
- # Numbers of redirects before raising an exception when trying to parse given url.
11
- # config.redirect_limit = 3
12
-
13
- # List of blacklisted urls you want to skip when searching for images.
14
- # config.blacklist_urls = [
15
- # %r{^http://ad\.doubleclick\.net/},
16
- # %r{^http://b\.scorecardresearch\.com/},
17
- # %r{^http://pixel\.quantserve\.com/},
18
- # %r{^http://s7\.addthis\.com/}
19
- # ]
20
-
21
- # Included Rmagick attributes for images. See http://www.imagemagick.org/RMagick/doc/
22
- # for more details.
23
- # 'source_url' is a custom attribute and should always be included since this
24
- # is where you'll find the image url.
25
- # config.image_attributes = %w(source_url size type)
26
-
27
- # Fetch 10 images maximum.
28
- # config.limit = 10
29
-
30
- # Return top 5 images only.
31
- # config.top = 5
32
-
33
- # Set user agent
34
- # config.user_agent = 'linkthumbnailer'
35
-
36
- # Enable or disable SSL verification
37
- # config.verify_ssl = true
38
-
39
- # HTTP open_timeout: The amount of time in seconds to wait for a connection to be opened.
40
- # config.http_timeout = 5
41
- end
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
- def rmagick_attributes
7
- LinkThumbnailer.logger.info "[DEPRECATION] rmagick_attributes is deprecated. Use image_attributes instead."
8
- image_attributes
9
- end
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
- def rmagick_attributes=(value)
12
- LinkThumbnailer.logger.info "[DEPRECATION] rmagick_attributes is deprecated. Use image_attributes instead."
13
- self.image_attributes = value
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,6 @@
1
+ module LinkThumbnailer
2
+ class Exceptions < StandardError; end
3
+ class RedirectLimit < Exceptions; end
4
+ class BadUriFormat < Exceptions; end
5
+ class ScraperInvalid < Exceptions; end
6
+ 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,11 @@
1
+ module LinkThumbnailer
2
+ module Graders
3
+ class Position < ::LinkThumbnailer::Graders::Base
4
+
5
+ def call(current_score)
6
+ 2.0 / description.position
7
+ end
8
+
9
+ end
10
+ end
11
+ 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,17 @@
1
+ module LinkThumbnailer
2
+ module ImageComparators
3
+ class Base
4
+
5
+ attr_reader :image
6
+
7
+ def initialize(image)
8
+ @image = image
9
+ end
10
+
11
+ def call
12
+ raise 'you must implement this method'
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ module LinkThumbnailer
2
+ module ImageComparators
3
+ class Size < ::LinkThumbnailer::ImageComparators::Base
4
+
5
+ def call(other)
6
+ (other.size.min ** 2) <=> (image.size.min ** 2)
7
+ end
8
+
9
+ end
10
+ end
11
+ 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,15 @@
1
+ require 'fastimage'
2
+
3
+ module LinkThumbnailer
4
+ module ImageParsers
5
+ class Size
6
+
7
+ def self.perform(image)
8
+ ::FastImage.size(image.src, raise_on_failure: true)
9
+ rescue ::FastImage::FastImageException
10
+ [0, 0]
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'fastimage'
2
+
3
+ module LinkThumbnailer
4
+ module ImageParsers
5
+ class Type
6
+
7
+ def self.perform(image)
8
+ ::FastImage.type(image.src, raise_on_failure: true)
9
+ rescue ::FastImage::FastImageException
10
+ :jpg
11
+ end
12
+
13
+ end
14
+ end
15
+ 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,16 @@
1
+ module LinkThumbnailer
2
+ class Model
3
+
4
+ def to_json(*args)
5
+ as_json.to_json(*args)
6
+ end
7
+
8
+ private
9
+
10
+ def sanitize(str)
11
+ return unless str
12
+ str.strip.gsub(/[\r\n\f]+/, "\n")
13
+ end
14
+
15
+ end
16
+ 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