kt-paperclip-vips 1.2.2 → 1.2.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e4aa0400c5db1aca28cf71692d749f5693bccfa4ac56d5cbd6599d10060423c3
4
- data.tar.gz: 99c3a302cae0af2f37c24918b6bfbfffca917cde6640fa18e013e6dd934bfc6e
3
+ metadata.gz: 5abb1916de9e20f18378d68ad36d1ad68444d9f4810b2af60a503f061e62173b
4
+ data.tar.gz: '038faff11b80ab241544d7afd510c3fbff8907be56e5abe6c485872fc735a3ab'
5
5
  SHA512:
6
- metadata.gz: aa8aee51bc040cd4a3bcb5ee2d2a90dffde49d602db8def2b42a50a284998cb310d49f2eabf7e109b16c5a8c2444f8a37728074372d581e1d6987ec06a2bc3c1
7
- data.tar.gz: 7a538b91a744206fe7dfa52eb80c8cb9d21085d2bb4fb23ed0f84498d70459149a36f2665a8f8fc27c033a638adc9007c9cd46dc360174508998d1ecc241c7f5
6
+ metadata.gz: 4f189349bf4e1dc8b3a56799ec1a1639c9e47810200aa9818eadb2fc5f8d2c6f1a0df69d27abcb3d129a6a76a70fedf1e91d79f3522fcb120c9ab5261dad63e9
7
+ data.tar.gz: '082eda71b1c8cbcb2b3f99713036e0944cea35c3c88f45fe87e72c6c6b6a4f5063a946ce7fac2edc0cda87b501444c26d518d800c0f180026850189b7b2fe2a1'
data/.rubocop.yml ADDED
@@ -0,0 +1,135 @@
1
+ plugins:
2
+ - rubocop-performance
3
+ - rubocop-rake
4
+ - rubocop-rspec
5
+
6
+ AllCops:
7
+ TargetRubyVersion: 3.2
8
+ DisabledByDefault: false
9
+ DisplayCopNames: true
10
+ NewCops: enable
11
+ Exclude:
12
+ - "**/bin/*"
13
+ - "**/config.ru"
14
+ - "**/db/**/*"
15
+ - "**/schema.rb"
16
+ - "**/node_modules/**/*"
17
+ - "**/vendor/**/*"
18
+ - "**/vendor/**/*.txt"
19
+ - "**/test/**/*"
20
+ - "**/tmp/**/*"
21
+
22
+ # Dim down rubocop's annoyance level below:
23
+
24
+ Layout/ArgumentAlignment:
25
+ Enabled: true
26
+ EnforcedStyle: with_fixed_indentation
27
+
28
+ Layout/CaseIndentation:
29
+ Enabled: true
30
+ EnforcedStyle: end
31
+
32
+ Layout/EndAlignment:
33
+ Enabled: true
34
+ EnforcedStyleAlignWith: variable
35
+ AutoCorrect: true
36
+
37
+ Layout/LineLength:
38
+ Exclude:
39
+ - app/views/**/*.rb
40
+ - app/components/**/*.rb
41
+ - lib/generators/**/*.rb
42
+ Max: 125
43
+
44
+ Layout/SpaceInsideBlockBraces:
45
+ Enabled: true
46
+ EnforcedStyleForEmptyBraces: space
47
+
48
+ Layout/SpaceInsideArrayLiteralBrackets:
49
+ EnforcedStyle: no_space
50
+
51
+ Layout/SpaceInsideHashLiteralBraces:
52
+ Enabled: true
53
+ EnforcedStyle: space
54
+ EnforcedStyleForEmptyBraces: no_space
55
+
56
+ Lint/MissingSuper:
57
+ Enabled: false
58
+
59
+ Metrics:
60
+ Enabled: false
61
+
62
+ Naming/FileName:
63
+ Exclude:
64
+ - lib/paperclip-vips.rb
65
+
66
+ RSpec/ExampleLength:
67
+ Enabled: false
68
+
69
+ RSpec/IndexedLet:
70
+ Enabled: false
71
+
72
+ RSpec/AlignLeftLetBrace:
73
+ Enabled: true
74
+
75
+ RSpec/MultipleExpectations:
76
+ Enabled: false
77
+
78
+ RSpec/MultipleMemoizedHelpers:
79
+ Max: 10
80
+
81
+ RSpec/NestedGroups:
82
+ Max: 4
83
+
84
+ RSpec/PendingWithoutReason:
85
+ Enabled: false
86
+
87
+ RSpec/PredicateMatcher:
88
+ Enabled: false
89
+
90
+ RSpec/SpecFilePathFormat:
91
+ Enabled: false
92
+
93
+ Style/ClassAndModuleChildren:
94
+ EnforcedStyle: nested
95
+ Exclude:
96
+ - app/events/**/*.rb
97
+ # - app/views/**/*.rb
98
+
99
+ Style/CommentedKeyword:
100
+ Enabled: false
101
+
102
+ Style/Documentation:
103
+ Enabled: false
104
+
105
+ Style/EmptyMethod:
106
+ Enabled: false
107
+
108
+ Style/FormatStringToken:
109
+ EnforcedStyle: template
110
+
111
+ Style/FrozenStringLiteralComment:
112
+ Enabled: true
113
+ EnforcedStyle: never
114
+
115
+ Style/HashSyntax:
116
+ Enabled: true
117
+ EnforcedShorthandSyntax: always
118
+
119
+ Style/PercentLiteralDelimiters:
120
+ PreferredDelimiters:
121
+ default: "()"
122
+ "%i": "[]"
123
+ "%I": "[]"
124
+ "%r": "{}"
125
+ "%w": "[]"
126
+ "%W": "[]"
127
+
128
+ Style/StringLiterals:
129
+ EnforcedStyle: double_quotes
130
+
131
+ Style/TrailingCommaInHashLiteral:
132
+ EnforcedStyleForMultiline: comma
133
+
134
+ Style/TrailingCommaInArrayLiteral:
135
+ EnforcedStyleForMultiline: comma
data/Gemfile CHANGED
@@ -4,7 +4,11 @@ source "https://rubygems.org"
4
4
  gemspec
5
5
 
6
6
  gem "bundler"
7
+ gem "byebug"
8
+ gem "gem-release"
7
9
  gem "rake"
8
10
  gem "rspec"
9
- gem "byebug"
10
- gem "gem-release"
11
+ gem "rubocop"
12
+ gem "rubocop-performance"
13
+ gem "rubocop-rake"
14
+ gem "rubocop-rspec"
data/README.md CHANGED
@@ -7,7 +7,7 @@ A custom paperclip processor that uses the [libvips image processing library](ht
7
7
  Add this line to your application's Gemfile:
8
8
 
9
9
  ```ruby
10
- gem 'paperclip-vips'
10
+ gem 'kt-paperclip-vips'
11
11
  ```
12
12
 
13
13
  And then execute:
@@ -16,7 +16,7 @@ And then execute:
16
16
 
17
17
  Or install it yourself as:
18
18
 
19
- $ gem install paperclip-vips
19
+ $ gem install kt-paperclip-vips
20
20
 
21
21
  Note: You will need to have libvips installed on your machine for this processor to work correctly.
22
22
 
data/Rakefile CHANGED
@@ -3,4 +3,4 @@ require "rspec/core/rake_task"
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ task default: :spec
data/bin/console CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "paperclip/vips"
4
+ require 'bundler/setup'
5
+ require 'paperclip/vips'
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
7
8
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +11,5 @@ require "paperclip/vips"
10
11
  # require "pry"
11
12
  # Pry.start
12
13
 
13
- require "irb"
14
+ require 'irb'
14
15
  IRB.start(__FILE__)
@@ -1,13 +1,13 @@
1
1
  module Paperclip
2
2
  class Vips < Processor
3
3
  attr_accessor :auto_orient, :convert_options, :current_geometry, :format, :source_file_options,
4
- :target_geometry, :whiny
4
+ :target_geometry, :whiny
5
5
 
6
6
  def initialize(file, options = {}, attachment = nil)
7
7
  super
8
8
 
9
9
  geometry = options[:geometry].to_s
10
- @should_crop = geometry[-1,1] == '#'
10
+ @should_crop = geometry[-1, 1] == "#"
11
11
  @target_geometry = options.fetch(:string_geometry_parser, Geometry).parse(geometry)
12
12
  @current_geometry = options.fetch(:file_geometry_parser, Geometry).from_file(@file)
13
13
  @whiny = options.fetch(:whiny, true)
@@ -27,96 +27,125 @@ module Paperclip
27
27
  destination = TempfileFactory.new.generate(filename)
28
28
 
29
29
  begin
30
- thumbnail = ::Vips::Image.thumbnail(source.path, width, height: crop ? height : nil, crop: crop) if @target_geometry
31
- thumbnail = ::Vips::Image.new_from_file(source.path) if !defined?(thumbnail) || thumbnail.nil?
30
+ if @target_geometry.present?
31
+ target_width = @target_geometry.width
32
+ target_height = @target_geometry.height
33
+ modifier = @target_geometry.modifier # e.g., ">", "#", etc.
34
+
35
+ # Use thumbnail for efficient resizing and cropping
36
+ crop = (modifier == "#")
37
+ thumbnail = ::Vips::Image.thumbnail(
38
+ source.path,
39
+ target_width,
40
+ height: crop ? target_height : nil,
41
+ size: (modifier == ">" ? :down : :both), # ">" means shrink only
42
+ crop: crop ? :centre : :none
43
+ )
44
+
45
+ # Additional cropping for exact "#" dimensions if needed
46
+ if crop && (thumbnail.width != target_width || thumbnail.height != target_height)
47
+ left = [0, (thumbnail.width - target_width) / 2].max
48
+ top = [0, (thumbnail.height - target_height) / 2].max
49
+ crop_width = [target_width, thumbnail.width - left].min
50
+ crop_height = [target_height, thumbnail.height - top].min
51
+ if crop_width.positive? && crop_height.positive?
52
+ thumbnail = thumbnail.crop(left, top, crop_width,
53
+ crop_height)
54
+ end
55
+ end
56
+ end
57
+
58
+ # Fallback to original image if no geometry
59
+ thumbnail = ::Vips::Image.new_from_file(source.path) unless defined?(thumbnail) && thumbnail
60
+
61
+ # Apply convert options
32
62
  thumbnail = process_convert_options(thumbnail)
33
- save_thumbnail(thumbnail, destination.path)
34
-
35
- rescue => e
36
- p e.message, e.backtrace
37
63
 
64
+ # Save the processed image
65
+ save_thumbnail(thumbnail, destination.path)
66
+ rescue StandardError => e
67
+ puts e.message, e.backtrace
38
68
  if @whiny
39
- message = "There was an error processing the thumbnail for #{@basename}:\n" + e.message
69
+ message = "There was an error processing the thumbnail for #{@basename}:\n#{e.message}"
40
70
  raise Paperclip::Error, message
41
71
  end
42
72
  end
43
73
 
44
- return destination
74
+ destination # Return the Tempfile object
45
75
  end
46
76
 
47
77
  private
48
- def crop
49
- if @should_crop
50
- return @options[:crop] || :centre
51
- end
52
78
 
53
- nil
54
- end
79
+ def crop
80
+ return @options[:crop] || :centre if @should_crop
55
81
 
56
- def current_format(file)
57
- extension = File.extname(file.path)
58
- return extension if extension.present?
82
+ nil
83
+ end
59
84
 
60
- extension = File.extname(file.original_filename)
61
- return extension if extension.present?
85
+ def current_format(file)
86
+ extension = File.extname(file.path)
87
+ return extension if extension.present?
62
88
 
63
- return ""
64
- end
89
+ extension = File.extname(file.original_filename)
90
+ return extension if extension.present?
65
91
 
66
- def width
67
- @target_geometry&.width || @current_geometry.width
68
- end
69
-
70
- def height
71
- @target_geometry&.height || @current_geometry.height
72
- end
73
-
74
- def process_convert_options(image)
75
- if image
76
- commands = parsed_convert_commands(@convert_options)
77
- commands.each do |cmd|
78
- image = ::Vips::Operation.call(cmd[:cmd], [image, *cmd[:args]], cmd[:optional] || {})
79
- end
80
- end
92
+ ""
93
+ end
81
94
 
82
- return image
83
- end
95
+ def width
96
+ @target_geometry&.width || @current_geometry.width
97
+ end
84
98
 
85
- def parsed_convert_commands(convert_options)
86
- begin
87
- commands = JSON.parse(convert_options, symbolize_names: true)
88
- rescue
89
- commands = []
90
- end
99
+ def height
100
+ @target_geometry&.height || @current_geometry.height
101
+ end
91
102
 
92
- if @auto_orient && commands.none? { _1[:cmd] == "autorot" }
93
- commands.unshift({ cmd: "autorot" })
94
- end
103
+ def process_convert_options(image)
104
+ if image && @convert_options.present?
105
+ # Handle string-based convert_options (e.g., "-quality 80 -strip")
106
+ quality = @convert_options[/quality (\d+)/, 1]&.to_i
107
+ strip = @convert_options.include?("-strip")
95
108
 
96
- return commands
97
- end
109
+ # Apply options via instance variables for save_thumbnail
110
+ @processed_quality = quality if quality
111
+ @processed_strip = strip if strip
98
112
 
99
- def save_thumbnail(thumbnail, path)
100
- case @current_format
101
- when ".jpeg", ".jpg"
102
- save_jpg(thumbnail, path)
103
- when ".gif"
104
- save_gif(thumbnail, path)
105
- when ".png"
106
- save_png(thumbnail, path)
113
+ # Handle JSON-based commands if present
114
+ commands = parsed_convert_commands(@convert_options)
115
+ commands.each do |cmd|
116
+ image = ::Vips::Operation.call(cmd[:cmd], [image, *cmd[:args]], cmd[:optional] || {})
107
117
  end
108
118
  end
119
+ image
120
+ end
109
121
 
110
- def save_jpg(thumbnail, path)
111
- thumbnail.jpegsave(path)
122
+ def parsed_convert_commands(convert_options)
123
+ begin
124
+ commands = JSON.parse(convert_options, symbolize_names: true)
125
+ rescue StandardError
126
+ commands = []
112
127
  end
113
128
 
114
- def save_gif(thumbnail, path)
115
- thumbnail.magicksave(path)
116
- end
129
+ commands.unshift({ cmd: "autorot" }) if @auto_orient && commands.none? { |cmd| cmd[:cmd] == "autorot" }
117
130
 
118
- def save_png(thumbnail, path)
119
- thumbnail.pngsave(path)
131
+ commands
132
+ end
133
+
134
+ def save_thumbnail(thumbnail, path)
135
+ quality = @processed_quality || 75
136
+ strip = @processed_strip || false
137
+
138
+ case @format.to_s.downcase
139
+ when ".jpeg", ".jpg", "jpeg", "jpg", "webp"
140
+ thumbnail.jpegsave(path, Q: quality, strip:)
141
+ when ".gif", "gif"
142
+ thumbnail.magicksave(path, strip:) # No quality for GIF
143
+ when ".png", "png"
144
+ compression = 9 - (quality / 11.1).floor # Map 0-100 to 9-0
145
+ thumbnail.pngsave(path, compression:, strip:)
146
+ else
147
+ thumbnail.write_to_file(path) # Fallback
120
148
  end
149
+ end
121
150
  end
122
151
  end
@@ -1,3 +1,3 @@
1
1
  module PaperclipVips
2
- VERSION = "1.2.2"
2
+ VERSION = "1.2.4".freeze
3
3
  end
@@ -5,6 +5,6 @@ require "paperclip-vips/paperclip/vips"
5
5
 
6
6
  module PaperclipVips
7
7
  def self.root
8
- Gem::Specification.find_by_name('paperclip-vips').gem_dir
8
+ Gem::Specification.find_by_name("kt-paperclip-vips").gem_dir
9
9
  end
10
10
  end
@@ -1,5 +1,4 @@
1
-
2
- lib = File.expand_path("../lib", __FILE__)
1
+ lib = File.expand_path("lib", __dir__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require "paperclip-vips/version"
5
4
 
@@ -9,19 +8,22 @@ Gem::Specification.new do |spec|
9
8
  spec.authors = ["Ken Greeff", "Mikael Henriksson"]
10
9
  spec.email = ["ken@kengreeff.com", "mikael@mhenrixon.com"]
11
10
 
12
- spec.summary = %q{Uses Ruby Vips to when creating thumbnails for faster generation.}
11
+ spec.summary = "Uses Ruby Vips to when creating thumbnails for faster generation."
13
12
  spec.homepage = "https://github.com/realhub/paperclip-vips"
14
13
  spec.license = "MIT"
15
14
 
15
+ spec.required_ruby_version = ">= 3.2.0"
16
+
16
17
  # Specify which files should be added to the gem when it is released.
17
18
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
19
20
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|Gemfile|mise.toml/bin)/}) }
20
21
  end
21
22
  spec.bindir = "exe"
22
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
24
  spec.require_paths = ["lib"]
24
25
 
25
- spec.add_runtime_dependency 'kt-paperclip', ">= 5.0.0"
26
- spec.add_runtime_dependency "ruby-vips", ">= 2.1"
26
+ spec.add_dependency "kt-paperclip", ">= 5.0.0"
27
+ spec.add_dependency "ruby-vips", ">= 2.1"
28
+ spec.metadata["rubygems_mfa_required"] = "true"
27
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kt-paperclip-vips
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ken Greeff
8
8
  - Mikael Henriksson
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-02-20 00:00:00.000000000 Z
11
+ date: 2025-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kt-paperclip
@@ -47,6 +47,7 @@ extra_rdoc_files: []
47
47
  files:
48
48
  - ".gitignore"
49
49
  - ".rspec"
50
+ - ".rubocop.yml"
50
51
  - ".travis.yml"
51
52
  - CHANGELOG.md
52
53
  - CODE_OF_CONDUCT.md
@@ -63,7 +64,8 @@ files:
63
64
  homepage: https://github.com/realhub/paperclip-vips
64
65
  licenses:
65
66
  - MIT
66
- metadata: {}
67
+ metadata:
68
+ rubygems_mfa_required: 'true'
67
69
  rdoc_options: []
68
70
  require_paths:
69
71
  - lib
@@ -71,7 +73,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
71
73
  requirements:
72
74
  - - ">="
73
75
  - !ruby/object:Gem::Version
74
- version: '0'
76
+ version: 3.2.0
75
77
  required_rubygems_version: !ruby/object:Gem::Requirement
76
78
  requirements:
77
79
  - - ">="