jr-paperclip 7.3.0 → 8.0.0.beta.1
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/.github/workflows/{test.yml → tests.yml} +19 -9
- data/.rubocop.yml +2 -1
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +1 -0
- data/NEWS +16 -1
- data/README.md +119 -8
- data/UPGRADING +5 -0
- data/VIPS_MIGRATION_GUIDE.md +131 -0
- data/features/basic_integration.feature +27 -0
- data/features/step_definitions/attachment_steps.rb +17 -0
- data/gemfiles/7.0.gemfile +1 -0
- data/gemfiles/7.1.gemfile +1 -0
- data/gemfiles/7.2.gemfile +1 -0
- data/gemfiles/8.0.gemfile +1 -0
- data/gemfiles/8.1.gemfile +1 -0
- data/lib/paperclip/attachment.rb +3 -2
- data/lib/paperclip/errors.rb +4 -5
- data/lib/paperclip/geometry.rb +3 -3
- data/lib/paperclip/geometry_detector_factory.rb +52 -12
- data/lib/paperclip/helpers.rb +18 -0
- data/lib/paperclip/processor.rb +36 -4
- data/lib/paperclip/thumbnail.rb +568 -62
- data/lib/paperclip/version.rb +1 -1
- data/lib/paperclip.rb +26 -9
- data/paperclip.gemspec +3 -2
- data/spec/paperclip/attachment_definitions_spec.rb +300 -0
- data/spec/paperclip/attachment_spec.rb +1 -1
- data/spec/paperclip/geometry_detector_spec.rb +81 -32
- data/spec/paperclip/geometry_spec.rb +8 -5
- data/spec/paperclip/helpers_spec.rb +49 -0
- data/spec/paperclip/lazy_thumbnail_compatibility_spec.rb +266 -0
- data/spec/paperclip/processor_spec.rb +35 -1
- data/spec/paperclip/style_spec.rb +58 -0
- data/spec/paperclip/thumbnail_custom_options_spec.rb +173 -0
- data/spec/paperclip/thumbnail_loader_options_spec.rb +53 -0
- data/spec/paperclip/thumbnail_security_spec.rb +42 -0
- data/spec/paperclip/thumbnail_spec.rb +1127 -172
- metadata +36 -4
|
@@ -1,31 +1,75 @@
|
|
|
1
1
|
module Paperclip
|
|
2
2
|
class GeometryDetector
|
|
3
|
-
def initialize(file)
|
|
3
|
+
def initialize(file, backend: nil)
|
|
4
4
|
@file = file
|
|
5
|
+
@backend = backend
|
|
5
6
|
raise_if_blank_file
|
|
6
7
|
end
|
|
7
8
|
|
|
8
9
|
def make
|
|
9
10
|
geometry = GeometryParser.new(geometry_string.strip).make
|
|
10
|
-
geometry || raise(Errors::
|
|
11
|
+
geometry || raise(Errors::NotIdentifiedByBackendError.new("Could not identify image size"))
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
private
|
|
14
15
|
|
|
15
16
|
def geometry_string
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
if resolve_backend == :vips
|
|
18
|
+
vips_geometry_string
|
|
19
|
+
else
|
|
20
|
+
imagemagick_geometry_string
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def resolve_backend
|
|
25
|
+
Paperclip.resolve_backend(@backend || Paperclip.options[:backend])
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def imagemagick_geometry_string
|
|
29
|
+
orientation = if Paperclip.options[:use_exif_orientation]
|
|
30
|
+
"%[exif:orientation]"
|
|
31
|
+
else
|
|
32
|
+
"1"
|
|
33
|
+
end
|
|
18
34
|
Paperclip.run(
|
|
19
|
-
Paperclip.options[:is_windows] ? "magick identify" : "identify",
|
|
35
|
+
(Paperclip.options[:is_windows] || Paperclip.imagemagick7?) ? "magick identify" : "identify",
|
|
20
36
|
"-format '%wx%h,#{orientation}' :file", {
|
|
21
|
-
file: "#{path}[0]"
|
|
37
|
+
file: "#{path}[0]",
|
|
22
38
|
},
|
|
23
39
|
swallow_stderr: true
|
|
24
40
|
)
|
|
25
41
|
rescue Terrapin::ExitStatusError
|
|
26
42
|
""
|
|
27
43
|
rescue Terrapin::CommandNotFoundError => e
|
|
28
|
-
|
|
44
|
+
raise Errors::CommandNotFoundError.new("Could not run the `identify` command. Please install ImageMagick.")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def vips_geometry_string
|
|
48
|
+
begin
|
|
49
|
+
require "vips"
|
|
50
|
+
rescue LoadError => e
|
|
51
|
+
raise Errors::CommandNotFoundError.new("Could not load ruby-vips. Please install libvips and the image_processing gem.")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
begin
|
|
55
|
+
# Use ruby-vips gem directly instead of shelling out to vipsheader
|
|
56
|
+
image = Vips::Image.new_from_file(path, access: :sequential)
|
|
57
|
+
width = image.width
|
|
58
|
+
height = image.height
|
|
59
|
+
|
|
60
|
+
orientation = "1"
|
|
61
|
+
if Paperclip.options[:use_exif_orientation]
|
|
62
|
+
begin
|
|
63
|
+
orientation = image.get("orientation").to_s
|
|
64
|
+
rescue Vips::Error
|
|
65
|
+
# Field might not exist
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
"#{width}x#{height},#{orientation}"
|
|
70
|
+
rescue Vips::Error
|
|
71
|
+
""
|
|
72
|
+
end
|
|
29
73
|
end
|
|
30
74
|
|
|
31
75
|
def path
|
|
@@ -34,12 +78,8 @@ module Paperclip
|
|
|
34
78
|
|
|
35
79
|
def raise_if_blank_file
|
|
36
80
|
if path.blank?
|
|
37
|
-
raise Errors::
|
|
81
|
+
raise Errors::NotIdentifiedByBackendError.new("Cannot find the geometry of a file with a blank name")
|
|
38
82
|
end
|
|
39
83
|
end
|
|
40
|
-
|
|
41
|
-
def raise_because_imagemagick_missing
|
|
42
|
-
raise Errors::CommandNotFoundError.new("Could not run the `identify` command. Please install ImageMagick.")
|
|
43
|
-
end
|
|
44
84
|
end
|
|
45
85
|
end
|
data/lib/paperclip/helpers.rb
CHANGED
|
@@ -56,5 +56,23 @@ module Paperclip
|
|
|
56
56
|
def reset_duplicate_clash_check!
|
|
57
57
|
@names_url = nil
|
|
58
58
|
end
|
|
59
|
+
|
|
60
|
+
def imagemagick7?
|
|
61
|
+
return @imagemagick7 if instance_variable_defined?(:@imagemagick7)
|
|
62
|
+
|
|
63
|
+
@imagemagick7 = !!which("magick")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# https://github.com/minimagick/minimagick/blob/master/lib/mini_magick/utilities.rb#L9-L24
|
|
67
|
+
def which(cmd)
|
|
68
|
+
exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""]
|
|
69
|
+
(ENV["PATH"] || "").split(File::PATH_SEPARATOR).each do |path|
|
|
70
|
+
exts.each do |ext|
|
|
71
|
+
exe = File.join(path, "#{cmd}#{ext}")
|
|
72
|
+
return exe if File.executable? exe
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
nil
|
|
76
|
+
end
|
|
59
77
|
end
|
|
60
78
|
end
|
data/lib/paperclip/processor.rb
CHANGED
|
@@ -36,10 +36,18 @@ module Paperclip
|
|
|
36
36
|
# The convert method runs the convert binary with the provided arguments.
|
|
37
37
|
# See Paperclip.run for the available options.
|
|
38
38
|
def convert(arguments = "", local_options = {})
|
|
39
|
+
command =
|
|
40
|
+
if Paperclip.imagemagick7? # IMv7 on any OS
|
|
41
|
+
"magick"
|
|
42
|
+
elsif Paperclip.options[:is_windows] # IMv6 on Windows
|
|
43
|
+
"magick convert"
|
|
44
|
+
else
|
|
45
|
+
"convert"
|
|
46
|
+
end
|
|
39
47
|
Paperclip.run(
|
|
40
|
-
|
|
48
|
+
command,
|
|
41
49
|
arguments,
|
|
42
|
-
local_options
|
|
50
|
+
local_options,
|
|
43
51
|
)
|
|
44
52
|
end
|
|
45
53
|
|
|
@@ -47,10 +55,34 @@ module Paperclip
|
|
|
47
55
|
# See Paperclip.run for the available options.
|
|
48
56
|
def identify(arguments = "", local_options = {})
|
|
49
57
|
Paperclip.run(
|
|
50
|
-
Paperclip.options[:is_windows] ? "magick identify" : "identify",
|
|
58
|
+
(Paperclip.options[:is_windows] || Paperclip.imagemagick7?) ? "magick identify" : "identify",
|
|
51
59
|
arguments,
|
|
52
|
-
local_options
|
|
60
|
+
local_options,
|
|
53
61
|
)
|
|
54
62
|
end
|
|
63
|
+
|
|
64
|
+
# Runs libvips command
|
|
65
|
+
def vips(arguments = "", local_options = {})
|
|
66
|
+
Paperclip.run("vips", arguments, local_options)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Runs libvips header command
|
|
70
|
+
def vipsheader(arguments = "", local_options = {})
|
|
71
|
+
Paperclip.run("vipsheader", arguments, local_options)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Returns a Vips::Image object for the given file path.
|
|
75
|
+
# This provides access to the full ruby-vips API for image manipulation.
|
|
76
|
+
# @param file_path [String] Path to the image file
|
|
77
|
+
# @param options [Hash] Options to pass to Vips::Image.new_from_file
|
|
78
|
+
# @return [Vips::Image] The loaded image
|
|
79
|
+
def vips_image(file_path, **options)
|
|
80
|
+
begin
|
|
81
|
+
require "vips"
|
|
82
|
+
rescue LoadError
|
|
83
|
+
raise Errors::CommandNotFoundError.new("Could not load ruby-vips. Please install libvips and the vips gem.")
|
|
84
|
+
end
|
|
85
|
+
Vips::Image.new_from_file(file_path, **options)
|
|
86
|
+
end
|
|
55
87
|
end
|
|
56
88
|
end
|