retina_rails 1.0.4 → 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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -3
  3. data/.travis.yml +16 -4
  4. data/README.md +57 -29
  5. data/UPGRADING +7 -0
  6. data/UPGRADING.md +60 -0
  7. data/lib/retina_rails.rb +11 -7
  8. data/lib/retina_rails/extensions.rb +16 -0
  9. data/lib/retina_rails/extensions/carrierwave.rb +25 -0
  10. data/lib/retina_rails/extensions/paperclip.rb +23 -0
  11. data/lib/retina_rails/helpers.rb +42 -12
  12. data/lib/retina_rails/processors.rb +14 -0
  13. data/lib/retina_rails/processors/carrierwave.rb +49 -0
  14. data/lib/retina_rails/processors/paperclip.rb +30 -0
  15. data/lib/retina_rails/strategies.rb +6 -7
  16. data/lib/retina_rails/strategies/carrierwave.rb +56 -50
  17. data/lib/retina_rails/strategies/paperclip.rb +53 -55
  18. data/lib/retina_rails/version.rb +1 -1
  19. data/retina_rails.gemspec +11 -4
  20. data/spec/fixtures/db/retina_rails.sqlite3 +0 -0
  21. data/spec/helpers_spec.rb +87 -13
  22. data/spec/spec_helper.rb +10 -4
  23. data/spec/strategies/carrierwave_spec.rb +117 -154
  24. data/spec/strategies/paperclip_spec.rb +77 -104
  25. data/spec/support/carrierwave.rb +15 -0
  26. data/spec/support/file_string_io.rb +2 -0
  27. data/spec/support/paperclip.rb +9 -0
  28. data/spec/support/rails.rb +0 -11
  29. data/spec/support/schema.rb +8 -2
  30. metadata +53 -52
  31. data/lib/retina_rails/deprecation/carrierwave.rb +0 -23
  32. data/lib/retina_rails/deprecation/paperclip.rb +0 -23
  33. data/lib/retina_rails/exception.rb +0 -15
  34. data/spec/deprecation/carrierwave_spec.rb +0 -13
  35. data/spec/deprecation/paperclip_spec.rb +0 -14
  36. data/spec/fixtures/images/avatar.with.dots.jpeg +0 -0
  37. data/spec/fixtures/manifest.yml +0 -10
  38. data/vendor/assets/javascripts/retina.js +0 -113
@@ -0,0 +1,14 @@
1
+ module RetinaRails
2
+ module Processors
3
+
4
+ def self.include_processors
5
+ if defined?(::CarrierWave)
6
+ require 'retina_rails/processors/carrierwave'
7
+ end
8
+ if defined?(::Paperclip)
9
+ require 'retina_rails/processors/paperclip'
10
+ end
11
+ end
12
+
13
+ end # Processors
14
+ end # RetinaRails
@@ -0,0 +1,49 @@
1
+ module RetinaRails
2
+ module Processors
3
+ module CarrierWave
4
+
5
+ extend ActiveSupport::Concern
6
+
7
+ ##
8
+ # Stores the original dimensions of the image as a serialized Hash in to the model
9
+ #
10
+ def store_retina_dimensions
11
+ if model
12
+ width, height = `identify -format "%wx%h" #{file.path}`.split(/x/) ## Read dimensions
13
+
14
+ ## Set original height and width attributes on model
15
+
16
+ model.retina_dimensions = (model.retina_dimensions || {}).deep_merge!(
17
+ mounted_as => {
18
+ version_name => {
19
+ :width => width.to_i / 2,
20
+ :height => height.to_i / 2
21
+ }
22
+ }
23
+ )
24
+ end
25
+ end
26
+
27
+ ##
28
+ # Process retina quality of the image.
29
+ # Works with ImageMagick and MiniMagick
30
+ #
31
+ # === Parameters
32
+ #
33
+ # [percentage (Int)] quality in percentage
34
+ #
35
+ def retina_quality(percentage)
36
+ manipulate! do |img|
37
+ if defined?(Magick)
38
+ img.write(current_path) { self.quality = percentage } unless img.quality == percentage
39
+ elsif defined?(MiniMagick)
40
+ img.quality(percentage.to_s)
41
+ end
42
+ img = yield(img) if block_given?
43
+ img
44
+ end
45
+ end
46
+
47
+ end # CarrierWave
48
+ end # Processors
49
+ end # RetinaRails
@@ -0,0 +1,30 @@
1
+ module Paperclip
2
+ class SaveDimensions < Paperclip::Processor
3
+
4
+ ##
5
+ # Stores the original dimensions of the image as a serialized Hash in to the model
6
+ #
7
+ def make
8
+ model = attachment.instance
9
+ file_path = file.path rescue nil
10
+ style = options[:style]
11
+
12
+ if file_path
13
+ width, height = `identify -format "%wx%h" #{file_path}`.split(/x/) ## Read dimensions
14
+
15
+ ## Set original height and width attributes on model
16
+ model.retina_dimensions = (model.retina_dimensions || {}).deep_merge!(
17
+ attachment.name => {
18
+ style => {
19
+ :width => width.to_i / 2,
20
+ :height => height.to_i / 2
21
+ }
22
+ }
23
+ )
24
+ end
25
+
26
+ file
27
+ end
28
+
29
+ end # SaveDimensions
30
+ end # Paperclip
@@ -1,17 +1,16 @@
1
- require 'retina_rails/strategies/carrierwave'
2
- require 'retina_rails/strategies/paperclip'
3
-
4
1
  module RetinaRails
5
2
  module Strategies
6
3
 
7
4
  def self.include_strategies
8
5
  if defined?(::CarrierWave)
9
- ::CarrierWave::Uploader::Base.send(:include, RetinaRails::Strategies::CarrierWave::Base)
6
+ require 'retina_rails/strategies/carrierwave'
7
+ ::CarrierWave::Uploader::Base.send(:include, CarrierWave::Base)
10
8
  end
11
9
  if defined?(::Paperclip)
12
- ::ActiveRecord::Base.send(:include, RetinaRails::Strategies::Paperclip::Base)
10
+ require 'retina_rails/strategies/paperclip'
11
+ ::ActiveRecord::Base.send(:include, Paperclip::Base)
13
12
  end
14
13
  end
15
14
 
16
- end
17
- end
15
+ end # Strategies
16
+ end # RetinaRails
@@ -11,25 +11,57 @@ module RetinaRails
11
11
  include Uploader
12
12
  end
13
13
 
14
- end
14
+ end # ClassMethods
15
15
 
16
- end
16
+ end # Base
17
17
 
18
18
  module Uploader
19
19
 
20
20
  extend ActiveSupport::Concern
21
+ include Processors::CarrierWave
21
22
 
22
23
  module ClassMethods
23
24
 
25
+ ##
26
+ # Adds a new version to this uploader
27
+ #
28
+ # === Parameters
29
+ #
30
+ # [name (#to_sym)] name of the version
31
+ # [options (Hash)] optional options hash
32
+ # [&block (Proc)] a block to eval on this version of the uploader
33
+ #
34
+ # === Examples
35
+ #
36
+ # class MyUploader < CarrierWave::Uploader::Base
37
+ #
38
+ # retina!
39
+ #
40
+ # version :thumb do
41
+ # process :resize_to_fill => [30, 30]
42
+ # process :retina_quality => 25
43
+ # end
44
+ #
45
+ # version :thumb, :retina => false do
46
+ # process :resize_to_fill => [30, 30]
47
+ # end
48
+ #
49
+ # end
50
+ #
24
51
  def version(name, options={}, &block)
25
52
  super
26
53
 
27
- retina_version(name, { :if => options[:if] }) unless options[:retina] == false
54
+ optimize_retina!(name, { :if => options[:if] }) unless options[:retina] == false
28
55
  end
29
56
 
30
- # Define a retina version
31
- # This method will simply copy all settings and add a larger (retina) version
32
- def retina_version(name, options={})
57
+ ##
58
+ # Optimize version for retina displays
59
+ #
60
+ # === Parameters
61
+ #
62
+ # [name (Sym)] name of the version
63
+ #
64
+ def optimize_retina!(name, options={})
33
65
  config = versions[name]
34
66
  options[:retina] = false
35
67
 
@@ -43,65 +75,39 @@ module RetinaRails
43
75
 
44
76
  ## Define a retina version if processor is present
45
77
  if dimensions_processor
78
+ dimensions = dimensions_processor[1].dup
46
79
 
47
- processor_options = dimensions_processor[1].dup
80
+ width = dimensions[0] * 2
81
+ height = dimensions[1] * 2
48
82
 
49
- width = processor_options[0] * 2
50
- height = processor_options[1] * 2
83
+ 2.times { dimensions.delete_at(0) }
51
84
 
52
- 2.times { processor_options.delete_at(0) }
85
+ dimensions.insert(0, height)
86
+ dimensions.insert(0, width)
53
87
 
54
- processor_options.insert(0, height)
55
- processor_options.insert(0, width)
56
-
57
- version "#{name}_retina", options do
58
- process dimensions_processor[0] => processor_options
88
+ ## Override version with double height and width
89
+ version name, options do
90
+ process dimensions_processor[0] => dimensions
59
91
 
60
92
  quality_processor = nil
61
93
 
62
94
  ## Set other processors
63
95
  processors.each do |processor|
64
- process processor[0] => processor[1]
65
-
66
96
  quality_processor = true if processor[0] == :retina_quality
67
97
  end
68
98
 
69
99
  ## Set default quality if retina_quality is not defined
70
- process :retina_quality => 40 if quality_processor.nil?
71
- end
72
- end
73
- end
100
+ process :retina_quality => 60 if quality_processor.nil?
74
101
 
75
- end
76
-
77
- ## Set the correct filename for storage according to the convention (append @2x to filename)
78
- def full_filename(for_file)
79
- super.tap do |file_name|
80
- if version_name.to_s.include?('retina')
81
- has_extension = file_name.scan(/(jpg|jpeg|png|gif|bmp)/).any?
82
-
83
- regex = has_extension ? /(.*)\./ : /.*/
84
- file_name.sub!(regex, '\1@2x.').gsub!('retina_', '')
85
- end
86
- end
87
- end
88
-
89
- ## Set retina image quality
90
- def retina_quality(percentage)
91
- if version_name.to_s.include?('retina')
92
- manipulate! do |img|
93
- if defined?(Magick)
94
- img.write(current_path) { self.quality = percentage } unless img.quality == percentage
95
- elsif defined?(MiniMagick)
96
- img.quality(percentage.to_s)
102
+ ## Store dimensions
103
+ process :store_retina_dimensions
97
104
  end
98
- img = yield(img) if block_given?
99
- img
100
105
  end
101
106
  end
102
- end
103
107
 
104
- end
105
- end
106
- end
107
- end
108
+ end # ClassMethods
109
+
110
+ end # Uploader
111
+ end # CarrierWave
112
+ end # Strategies
113
+ end # RetinaRails
@@ -9,33 +9,59 @@ module RetinaRails
9
9
  module ClassMethods
10
10
 
11
11
  def retina!
12
+ serialize :retina_dimensions
13
+
12
14
  include Uploader
13
15
  end
14
16
 
15
- end
17
+ end # Class methods
16
18
 
17
- end
19
+ end # Base
18
20
 
19
21
  module Uploader
20
22
 
21
23
  extend ActiveSupport::Concern
22
24
 
23
- included do
24
-
25
- ## Override paperclip default options
26
- Extensions.override_default_options
27
-
28
- end
29
-
30
25
  module ClassMethods
31
26
 
27
+ ##
28
+ # Define an attachment with its options
29
+ #
30
+ # === Parameters
31
+ #
32
+ # [name (#to_sym)] name of the version
33
+ # [options (Hash)] optional options hash
34
+ #
35
+ # === Examples
36
+ #
37
+ # class Upload
38
+ #
39
+ # retina!
40
+ #
41
+ # has_attached_file :image,
42
+ # :styles => {
43
+ # :original => ["800x800", :jpg],
44
+ # :big => ["125x125#", :jpg]
45
+ # },
46
+ # :retina => true # Or
47
+ # :retina => { :quality => 25 } # Optional
48
+ #
49
+ # end
50
+ #
32
51
  def has_attached_file(name, options={})
33
52
  super
34
53
 
35
- has_attached_retina_file name if options[:retina]
54
+ optimize_retina! name unless options[:retina] == false
36
55
  end
37
56
 
38
- def has_attached_retina_file(name)
57
+ ##
58
+ # Optimize attachment for retina displays
59
+ #
60
+ # === Parameters
61
+ #
62
+ # [name (Sym)] name of the attachment
63
+ #
64
+ def optimize_retina!(name)
39
65
  attachment = attachment_definitions[name]
40
66
 
41
67
  ## Check for style definitions
@@ -44,7 +70,7 @@ module RetinaRails
44
70
  retina_options = if attachment[:retina].is_a?(Hash)
45
71
  attachment[:retina]
46
72
  else
47
- { :quality => 40 }
73
+ { :quality => 60 }
48
74
  end
49
75
 
50
76
  ## Get retina quality
@@ -67,64 +93,36 @@ module RetinaRails
67
93
  processor = dimensions.scan(/#|</).first
68
94
 
69
95
  new_dimensions = "#{width}x#{height}#{processor}"
70
- retina_styles["#{key}_retina".to_sym] = value.kind_of?(Array) ? [new_dimensions, value[1]] : new_dimensions
96
+ retina_styles[key.to_sym] = value.kind_of?(Array) ? [new_dimensions, value[1]] : new_dimensions
71
97
 
72
98
  ## Set quality convert option
73
99
  convert_option = convert_options[key] if convert_options
74
100
  convert_option = convert_option ? "#{convert_option} -quality #{retina_quality}" : "-quality #{retina_quality}"
75
- retina_convert_options["#{key}_retina".to_sym] = convert_option
101
+ retina_convert_options[key.to_sym] = convert_option
76
102
 
77
103
  end
78
104
 
79
- ## Append new retina optimzed styles
105
+ ## Override styles with new retina dimensions
80
106
  attachment[:styles].merge!(retina_styles)
81
107
 
82
108
  ## Set quality convert options
83
109
  attachment[:convert_options] = {} if attachment[:convert_options].nil?
84
110
  attachment[:convert_options].merge!(retina_convert_options)
85
111
 
86
- ## Make path work with retina optimization
87
- original_path = attachment[:path]
88
- attachment[:path] = Extensions.optimize_path(original_path) if original_path
89
-
90
- ## Make url work with retina optimization
91
- original_url = attachment[:url]
92
- attachment[:url] = Extensions.optimize_path(original_url) if original_url
93
-
94
- end
95
- end
96
-
97
- end
98
-
99
- module Extensions
100
-
101
- ## Insert :retina interpolation in url or path
102
- def self.optimize_path(path)
103
- path.scan(':retina').empty? ? path.gsub(':filename', ':basename.:extension').split('.').insert(-2, ':retina.').join : path
104
- end
105
-
106
- def self.override_default_options
107
-
108
- ## Remove _retina from style so it doesn't end up in filename
109
- ::Paperclip.interpolates :style do |attachment, style|
110
- style.to_s.end_with?('_retina') ? style.to_s[0..-8] : style
111
- end
112
+ ## Set save dimensions processor
113
+ if attachment[:processors]
114
+ attachment[:processors] << :save_dimensions
115
+ attachment[:processors] << :thumbnail
116
+ else
117
+ attachment[:processors] = [:thumbnail, :save_dimensions]
118
+ end
112
119
 
113
- ## Replace :retina with @2x if style ends with _retina
114
- ::Paperclip.interpolates :retina do |attachment, style|
115
- style.to_s.end_with?('_retina') ? '@2x' : ''
116
120
  end
117
-
118
- ## Make default url compatible with retina optimzer
119
- url = ::Paperclip::Attachment.default_options[:url]
120
- ::Paperclip::Attachment.default_options[:url] = optimize_path(url)
121
-
122
121
  end
123
122
 
124
- end
125
-
126
- end
123
+ end # ClassMethods
124
+ end # Uploader
127
125
 
128
- end
129
- end
130
- end
126
+ end # Paperclip
127
+ end # Strategies
128
+ end # RetinaRails
@@ -1,3 +1,3 @@
1
1
  module RetinaRails
2
- VERSION = "1.0.4"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -9,8 +9,8 @@ Gem::Specification.new do |gem|
9
9
  gem.authors = ['Johan van Zonneveld', 'Arjen Oosterkamp']
10
10
  gem.email = ['johan@vzonneveld.nl', 'mail@arjen.me']
11
11
  gem.homepage = 'https://github.com/jhnvz/retina_rails.git'
12
- gem.summary = %q{Makes your life easier optimizing for retina displays}
13
- gem.description = %q{Retina Rails automatically generates retina versions of your uploaded images (CarrierWave or Paperclip). It detects if a visitor has a retina display and if so it displays the @2x version}
12
+ gem.summary = %q{Makes your life easier optimizing your application for retina displays}
13
+ gem.description = %q{Retina Rails makes your application use high-resolution images by default. It automatically optimizes uploaded images (CarrierWave or Paperclip) for retina displays by making them twice the size and reducing the quality.}
14
14
  gem.license = 'MIT'
15
15
 
16
16
  gem.files = `git ls-files`.split($/)
@@ -23,11 +23,18 @@ Gem::Specification.new do |gem|
23
23
  gem.add_development_dependency 'rspec', '>= 2.3'
24
24
  gem.add_development_dependency 'rspec-rails', '~> 2.0'
25
25
  gem.add_development_dependency 'carrierwave'
26
- gem.add_development_dependency 'paperclip', '< 4.0'
26
+ gem.add_development_dependency 'paperclip'
27
27
  gem.add_development_dependency 'rmagick'
28
28
  gem.add_development_dependency 'sqlite3'
29
29
  gem.add_development_dependency 'coveralls'
30
30
 
31
+ if RUBY_VERSION > '1.9.2'
32
+ gem.add_dependency 'rails', '>= 3.2.0'
33
+ else
34
+ gem.add_dependency 'rails', '>= 3.2.0', '< 4.0.0'
35
+ end
31
36
 
32
- gem.add_dependency 'rails', '>= 3.2.0', '< 4.0.0'
37
+ if File.exists?('UPGRADING')
38
+ gem.post_install_message = File.read("UPGRADING")
39
+ end
33
40
  end