jekyll_picture_tag 1.8.0 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -0
  3. data/.travis.yml +4 -7
  4. data/Dockerfile +9 -0
  5. data/docs/Gemfile.lock +183 -88
  6. data/docs/contributing.md +50 -16
  7. data/docs/example_presets.md +1 -1
  8. data/docs/global_configuration.md +55 -2
  9. data/docs/index.md +27 -21
  10. data/docs/installation.md +22 -7
  11. data/docs/presets.md +137 -55
  12. data/docs/releases.md +20 -1
  13. data/docs/usage.md +83 -39
  14. data/jekyll_picture_tag.gemspec +1 -1
  15. data/lib/jekyll_picture_tag.rb +28 -10
  16. data/lib/jekyll_picture_tag/cache.rb +3 -0
  17. data/lib/jekyll_picture_tag/cache/base.rb +59 -0
  18. data/lib/jekyll_picture_tag/cache/generated.rb +20 -0
  19. data/lib/jekyll_picture_tag/cache/source.rb +19 -0
  20. data/lib/jekyll_picture_tag/defaults/global.yml +2 -0
  21. data/lib/jekyll_picture_tag/defaults/presets.yml +2 -0
  22. data/lib/jekyll_picture_tag/generated_image.rb +85 -20
  23. data/lib/jekyll_picture_tag/img_uri.rb +1 -0
  24. data/lib/jekyll_picture_tag/instructions.rb +1 -0
  25. data/lib/jekyll_picture_tag/instructions/arg_splitter.rb +69 -0
  26. data/lib/jekyll_picture_tag/instructions/configuration.rb +47 -11
  27. data/lib/jekyll_picture_tag/instructions/preset.rb +35 -14
  28. data/lib/jekyll_picture_tag/instructions/set.rb +18 -8
  29. data/lib/jekyll_picture_tag/instructions/tag_parser.rb +59 -69
  30. data/lib/jekyll_picture_tag/output_formats/basic.rb +42 -11
  31. data/lib/jekyll_picture_tag/output_formats/img.rb +11 -0
  32. data/lib/jekyll_picture_tag/output_formats/picture.rb +22 -0
  33. data/lib/jekyll_picture_tag/router.rb +17 -0
  34. data/lib/jekyll_picture_tag/source_image.rb +60 -39
  35. data/lib/jekyll_picture_tag/srcsets/basic.rb +54 -19
  36. data/lib/jekyll_picture_tag/srcsets/pixel_ratio.rb +1 -3
  37. data/lib/jekyll_picture_tag/srcsets/width.rb +1 -1
  38. data/lib/jekyll_picture_tag/utils.rb +18 -0
  39. data/lib/jekyll_picture_tag/version.rb +1 -1
  40. data/readme.md +40 -16
  41. metadata +14 -8
@@ -1,7 +1,26 @@
1
1
  ---
2
2
  ---
3
3
  # Release History
4
-
4
+ * 1.11.0 July 27, 2020
5
+ * **Width and height attribute support!** Begone, page reflow.
6
+ * Cache image information between builds
7
+ * Change image naming format. This update will trigger all images to be regenerated, so you may
8
+ want to delete your generated images folder beforehand.
9
+ * 1.10.2 July 6, 2020
10
+ * Bugfix for fallback image files not actually getting generated
11
+ * 1.10.1 July 2, 2020
12
+ * Bugfix for erroneously regenerated images
13
+ * 1.10.0 May 11, 2020
14
+ * **Image Cropping support!** access the power of ImageMagick's `crop` function.
15
+ * Don't issue a warning when `default` preset is not found.
16
+ * Documentation improvements
17
+ * 1.9.0 Feb 2, 2020
18
+ * Add `fast_build` global setting
19
+ * Add `disabled` global setting
20
+ * Reduce unnecessary disk IO; sites with many source images should see build times improve when
21
+ no new images need to be generated.
22
+ * Add support for empty attributes; specifically so best-practice for decorative images (`alt=""`)
23
+ is possible.
5
24
  * 1.8.0 Nov 25, 2019
6
25
  * Add `data_sizes` setting for the `data_` family of output formats.
7
26
  * 1.7.1 Nov 14, 2019
@@ -1,65 +1,108 @@
1
1
  ---
2
2
  ---
3
+
3
4
  # How to use the Liquid Tag:
4
5
 
6
+ This section describes how to use JPT's liquid tag; what options it takes and what kind of information you can pass through it to influence the form of the final HTML-markup.
7
+
5
8
  ## Format:
6
9
 
7
10
  {% raw %}
8
- `{% picture [preset] (base image) [alternate images] [attributes] %}`
11
+ `{% picture [preset] (image) [crop] [alternate images & crops] [attributes] %}`
9
12
  {% endraw %}
10
13
 
11
14
  The only required argument is the base image. Line breaks and extra spaces are fine, and you can
12
15
  use liquid variables anywhere.
13
16
 
17
+ The `preset` determines the actual HTML code that gets written to your files;
18
+ it is basically a recipy that takes information that you provide in the
19
+ liquid tag and turns it into HTML markup. When the `preset` is omitted
20
+ default settings will be used, in the simplest case resulting in an `img`-tag
21
+ containing an srcset pointing to your newly generated image sizes. You are
22
+ free to override the `default` preset and define your own presets, giving
23
+ full flexibility in what JPT will write to your files. See [markup preset]({{
24
+ site.baseurl }}/presets#markup-presets) for more information on this.
25
+
14
26
  ## Examples:
15
27
 
16
28
  {% raw %}
17
29
  `{% picture example.jpg %}`
18
30
 
19
- `{% picture thumbnail example.jpg --alt Example Image %}`
31
+ `{% picture {{ page.example_liquid_picture_var }} %}`
32
+
33
+ `{% picture thumbnail example.jpg 1:1 --alt Example Image %}`
20
34
 
21
- `{% picture example.jpg --picture class="attribute-demo" %}`
35
+ `{% picture example.jpg 16:9 north --picture class="attribute-demo" %}`
22
36
 
23
37
  `{% picture blog_index {{ post.image }} --link {{ post.url }} %}`
24
38
 
25
39
  `{% picture "some example.jpg" mobile: other\ example.jpg %}`
26
40
 
27
41
  ```md
28
- {% picture
29
- hero
30
- example.jpg
31
- tablet: example_cropped.jpg
32
- mobile: example_cropped_more.jpg
33
- --alt Happy Puppy
34
- --picture class="hero"
42
+ {% picture
43
+ hero
44
+ example.jpg 16:9 east
45
+ tablet: example_cropped.jpg 3:2 east
46
+ mobile: example_cropped_more.jpg 1:1-50+0 east
47
+ --alt Happy Puppy
48
+ --picture class="hero"
35
49
  --link /
36
50
  %}
37
51
  ```
52
+
38
53
  {% endraw %}
39
54
 
40
55
  ## Argument reference
41
56
 
42
57
  Given in order:
43
58
 
44
- * **Preset**
59
+ - **Preset**
45
60
 
46
61
  Select a [markup preset]({{ site.baseurl }}/presets#markup-presets), or omit to use the `default` preset. Presets
47
62
  are collections of settings that determine nearly everything about JPT's output, from the image
48
- formats used to the exact format your markup will take.
63
+ formats used to the exact format your final HTML-markup will take.
49
64
 
50
- * **Base Image** (Required)
65
+ - **Base Image** (Required)
51
66
 
52
67
  Can be any raster image (as long as you have the required ImageMagick delegate). Relative to
53
68
  jekyll's root directory, or the `source` [setting]({{ site.baseurl }}/global_configuration) if you've configured it.
54
69
 
55
- For filenames with spaces, either use double quotes (`"my image.jpg"`) or a backslash (`my\
56
- image.jpg`).
70
+ For filenames with spaces, either use double quotes (`"my image.jpg"`) or a backslash (`my\ image.jpg`).
71
+
72
+ - **Crop**
73
+
74
+ **Check the [ installation guide ](installation) before using this feature.**
57
75
 
58
- * **Alternate images**
76
+ Crop an image to a given aspect ratio or size. This argument is given as a `geometry` and
77
+ (optionally) a `gravity`, which can appear in either order and are thin wrappers around
78
+ ImageMagick's [geometry](http://www.imagemagick.org/script/command-line-processing.php#geometry)
79
+ and [gravity](http://www.imagemagick.org/script/command-line-options.php#gravity) settings. The
80
+ values given here will override the preset settings (if present), can be given after every image,
81
+ and apply only to the preceding image.
59
82
 
60
- *Format:* `(media query preset): (filename) (...)`
83
+ Geometry can take many forms, but most likely you'll want to set an aspect ratio-- given in the
84
+ standard `width:height` ratio such as `3:2`. Gravity sets which portion of the image to keep, and
85
+ is given in compass directions (`north`, `southeast`, etc) or `center` (default). Cropping happens
86
+ before resizing; the preset `widths` setting is a post-crop value.
61
87
 
62
- *Example:* `tablet: img_cropped.jpg mobile: img_cropped_more.jpg`
88
+ If you'd like more fine-grained control, this can be offset by appending `+|-x` and (optionally)
89
+ `y` pixel values to the _geometry_ (not the gravity!). Example: `1:1+400 west` means "Crop to a
90
+ 1:1 aspect ratio, starting 400 pixels from the left side.", and `north 3:2+0+100` means "Crop to
91
+ 3:2, starting 100 pixels from the top." These can get a bit persnickety; there's nothing to stop
92
+ you from running off the side of the image. Pay attention.
93
+
94
+ For detailed documentation, see ImageMagick's
95
+ [crop](http://www.imagemagick.org/script/command-line-options.php#crop) tool.
96
+
97
+ _Note:_ If you do a lot of trial and error with these, it's a good idea to manually delete your
98
+ generated images folder more often as each change will build a new set of images without removing
99
+ the old ones.
100
+
101
+ - **Alternate images**
102
+
103
+ _Format:_ `(media query preset): (filename) (...)`
104
+
105
+ _Example:_ `tablet: img_cropped.jpg mobile: img_cropped_more.jpg`
63
106
 
64
107
  Optionally specify any number of alternate base images for given [screen
65
108
  sizes]({{ site.baseurl }}/presets/#media-presets) (specified in `_data/picture.yml`). This is called [art
@@ -70,44 +113,45 @@ Given in order:
70
113
  be provided to the browser in reverse order, and it will select the first one with an applicable
71
114
  media query.
72
115
 
73
- * **Attributes**
116
+ - **Attributes**
74
117
 
75
118
  Optionally specify any number of HTML attributes, or an href target. These will be added to any
76
119
  attributes you've set in a preset.
77
120
 
78
- * **`--link`**
121
+ - **`--link`**
122
+
123
+ _Format:_ `--link (some url)`
79
124
 
80
- *Format:* `--link (some url)`
125
+ _Examples_: `--link https://example.com`, `--link /blog/some_post/`
81
126
 
82
- *Examples*: `--link https://example.com`, `--link /blog/some_post/`
127
+ Wrap the image in an anchor tag, with the `href` attribute set to whatever value you give it.
128
+ This will override automatic source image linking, if you have enabled it.
83
129
 
84
- Wrap the image in an anchor tag, with the `href` attribute set to whatever value you give it.
85
- This will override automatic source image linking, if you have enabled it.
130
+ **Note**: If you get either mangled HTML or extra {::nomarkdown} tags when using this, read
131
+ [here]({{ site.baseurl }}/notes).
86
132
 
87
- **Note**: If you get either mangled HTML or extra {::nomarkdown} tags when using this, read
88
- [here]({{ site.baseurl }}/notes).
133
+ - **`--alt`**
89
134
 
90
- * **`--alt`**
91
-
92
- *Format:* `--alt (alt text)`
135
+ _Format:_ `--alt (alt text)`
93
136
 
94
- *Example:* `--alt Here is my alt text!`
137
+ _Example:_ `--alt Here is my alt text!`
95
138
 
96
139
  Convenience shortcut for `--img alt="..."`
97
-
98
- * **`--(element)`**
99
140
 
100
- *Format:* `--(picture|img|source|a|parent) (Standard HTML attributes)`
141
+ - **`--(element)`**
142
+
143
+ _Format:_ `--(picture|img|source|a|parent) (Standard HTML attributes)`
101
144
 
102
- *Example:* `--img class="awesome-fade-in" id="coolio" --a data-awesomeness="11"`
145
+ _Example:_ `--img class="awesome-fade-in" id="coolio" --a data-awesomeness="11"`
103
146
 
104
147
  Apply attributes to a given HTML element. Your options are:
105
148
 
106
- * `picture`
107
- * `img`
108
- * `source`
109
- * `a` (anchor tag)
110
- * `parent`
149
+ - `picture`
150
+ - `img`
151
+ - `source`
152
+ - `a` (anchor tag)
153
+ - `parent`
111
154
 
112
155
  `--parent` will be applied to the `<picture>` if present, otherwise the `<img>`; useful when
113
156
  using an `auto` output format.
157
+ **Note:** Attributes that are set in the liquid picture tag, but don't occur in the used `preset` will be ignored (e.g. adding `--picture class="cool-css"` with a preset that does not write a html `<picture>` tag).
@@ -40,7 +40,7 @@ Gem::Specification.new do |spec|
40
40
  spec.add_dependency 'addressable', '~> 2.6'
41
41
  spec.add_dependency 'mime-types', '~> 3'
42
42
  spec.add_dependency 'mini_magick', '~> 4'
43
- spec.add_dependency 'objective_elements', '~> 1.1.1'
43
+ spec.add_dependency 'objective_elements', '~> 1.1.2'
44
44
 
45
45
  spec.add_runtime_dependency 'jekyll', '< 5'
46
46
  end
@@ -9,6 +9,7 @@ require_relative 'jekyll_picture_tag/srcsets'
9
9
  require_relative 'jekyll_picture_tag/utils'
10
10
  require_relative 'jekyll_picture_tag/img_uri'
11
11
  require_relative 'jekyll_picture_tag/router'
12
+ require_relative 'jekyll_picture_tag/cache'
12
13
 
13
14
  # Title: Jekyll Picture Tag
14
15
  # Authors: Rob Wierzbowski : @robwierzbowski
@@ -18,9 +19,9 @@ require_relative 'jekyll_picture_tag/router'
18
19
  #
19
20
  # Description: Easy responsive images for Jekyll.
20
21
  #
21
- # Download: https://github.com/rbuchberger/jekyll_picture_tag
22
- # Documentation: https://github.com/rbuchberger/jekyll_picture_tag/readme.md
23
- # Issues: https://github.com/rbuchberger/jekyll_picture_tag/issues
22
+ # Download: https://rubygems.org/gems/jekyll_picture_tag
23
+ # Documentation: https://rbuchberger.github.io/jekyll_picture_tag/
24
+ # Issues: https://github.com/rbuchberger/jekyll_picture_tag/
24
25
  #
25
26
  # Syntax:
26
27
  # {% picture [preset] img.jpg [media_query: alt-img.jpg] [attributes] %}
@@ -39,30 +40,47 @@ require_relative 'jekyll_picture_tag/router'
39
40
  #
40
41
  # See the documentation for full configuration and usage instructions.
41
42
  module PictureTag
43
+ # The router module is important. If you're looking for the actual code which
44
+ # handles a `PictureTag.(some method)`, start there.
42
45
  extend Router
46
+
43
47
  ROOT_PATH = __dir__
44
48
 
45
49
  # This is the actual liquid tag, which provides the interface with Jekyll.
46
50
  class Picture < Liquid::Tag
51
+ # First jekyll initializes our class with a few arguments, of which we only
52
+ # care about the params (arguments passed to the liquid tag). Jekyll makes
53
+ # no attempt to parse them; they're given as a string.
47
54
  def initialize(tag_name, raw_params, tokens)
48
55
  @raw_params = raw_params
49
56
  super
50
57
  end
51
58
 
59
+ # Then jekyll calls the 'render' method and passes it a mostly undocumented
60
+ # context object, which appears to hold the entire site including its
61
+ # configuration and the parsed _data dir.
52
62
  def render(context)
53
- # Jekyll passes in a mostly undocumented context object, which appears to
54
- # hold the entire site, including configuration and the _data dir.
63
+ setup(context)
64
+
65
+ if PictureTag.disabled?
66
+ ''
67
+ else
68
+ PictureTag.output_class.new.to_s
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def setup(context)
55
75
  PictureTag.context = context
56
76
 
57
- # The instruction set depends on both the context and the tag parameters:
77
+ # Now that we have both the tag parameters and the context object, we can
78
+ # build our instruction set.
58
79
  PictureTag.instructions = Instructions::Set.new(@raw_params)
59
80
 
60
81
  # We need to explicitly prevent jekyll from overwriting our generated
61
- # files:
82
+ # image files:
62
83
  Utils.keep_files
63
-
64
- # Return a string:
65
- PictureTag.output_class.new.to_s
66
84
  end
67
85
  end
68
86
  end
@@ -0,0 +1,3 @@
1
+ require_relative 'cache/base'
2
+ require_relative 'cache/source'
3
+ require_relative 'cache/generated'
@@ -0,0 +1,59 @@
1
+ require 'json'
2
+
3
+ module PictureTag
4
+ module Cache
5
+ # Basic image information cache functionality
6
+ module Base
7
+ def initialize(base_name)
8
+ @base_name = base_name
9
+ end
10
+
11
+ def [](key)
12
+ data[key]
13
+ end
14
+
15
+ def []=(key, value)
16
+ raise ArgumentError unless template.keys.include? key
17
+
18
+ data[key] = value
19
+ end
20
+
21
+ # Call after updating data.
22
+ def write
23
+ FileUtils.mkdir_p(File.join(base_directory, sub_directory))
24
+
25
+ File.open(filename, 'w+') do |f|
26
+ f.write JSON.generate(data)
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def data
33
+ @data ||= if File.exist?(filename)
34
+ JSON.parse(File.read(filename)).transform_keys(&:to_sym)
35
+ else
36
+ template
37
+ end
38
+ end
39
+
40
+ # /home/dave/my_blog/.jekyll-cache/jpt/(cache_dir)/assets/myimage.jpg.json
41
+ # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42
+ def base_directory
43
+ File.join(PictureTag.site.cache_dir, 'jpt', cache_dir)
44
+ end
45
+
46
+ # /home/dave/my_blog/.jekyll-cache/jpt/(cache_dir)/assets/myimage.jpg.json
47
+ # ^^^^^^^^
48
+ def sub_directory
49
+ File.dirname(@base_name)
50
+ end
51
+
52
+ # /home/dave/my_blog/.jekyll-cache/jpt/somefolder/myimage.jpg.json
53
+ # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
54
+ def filename
55
+ File.join(base_directory, @base_name + '.json')
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,20 @@
1
+ module PictureTag
2
+ module Cache
3
+ # Caches generated image details, so we can skip expensive operations whenever
4
+ # possible.
5
+ # Stored width and height are values for the source image, after cropping.
6
+ class Generated
7
+ include Base
8
+
9
+ private
10
+
11
+ def cache_dir
12
+ 'generated'
13
+ end
14
+
15
+ def template
16
+ { width: nil, height: nil }
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module PictureTag
2
+ module Cache
3
+ # Caches source image details, so we can skip expensive operations whenever
4
+ # possible.
5
+ class Source
6
+ include Base
7
+
8
+ private
9
+
10
+ def template
11
+ { digest: nil, width: nil, height: nil }
12
+ end
13
+
14
+ def cache_dir
15
+ 'source'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -7,3 +7,5 @@ picture:
7
7
  cdn_environments: ['production']
8
8
  nomarkdown: true
9
9
  ignore_missing_images: false
10
+ disabled: false
11
+ fast_build: false
@@ -7,3 +7,5 @@ noscript: false
7
7
  link_source: false
8
8
  quality: 75
9
9
  data_sizes: true
10
+ gravity: center
11
+ dimension_attributes: false
@@ -1,47 +1,104 @@
1
1
  require 'mini_magick'
2
2
 
3
3
  module PictureTag
4
- # Generated Image
5
- # Represents a generated source file.
4
+ # Represents a generated image file.
6
5
  class GeneratedImage
7
6
  attr_reader :width, :format
7
+
8
8
  include MiniMagick
9
9
 
10
- def initialize(source_file:, width:, format:)
10
+ def initialize(source_file:, width:, format:, crop: nil, gravity: '')
11
11
  @source = source_file
12
12
  @width = width
13
13
  @format = process_format format
14
+ @crop = crop
15
+ @gravity = gravity
16
+ end
14
17
 
15
- generate_image unless File.exist?(absolute_filename) || @source.missing
18
+ def exists?
19
+ File.exist?(absolute_filename)
16
20
  end
17
21
 
18
- def name
19
- "#{@source.base_name}-#{@width}-#{@source.digest}.#{@format}"
22
+ def generate
23
+ generate_image unless @source.missing || exists?
20
24
  end
21
25
 
26
+ # /home/dave/my_blog/_site/generated/somefolder/myimage-100-123abc.jpg
27
+ # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
22
28
  def absolute_filename
23
29
  @absolute_filename ||= File.join(PictureTag.dest_dir, name)
24
30
  end
25
31
 
32
+ # /home/dave/my_blog/_site/generated/somefolder/myimage-100-123abc.jpg
33
+ # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
34
+ def name
35
+ @name ||= "#{@source.base_name}-#{@width}-#{id}.#{@format}"
36
+ end
37
+
38
+ # https://example.com/assets/images/myimage-100-123abc.jpg
39
+ # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26
40
  def uri
27
41
  ImgURI.new(name).to_s
28
42
  end
29
43
 
44
+ # Post crop
45
+ def source_width
46
+ update_cache unless cache[:width]
47
+
48
+ cache[:width]
49
+ end
50
+
51
+ # Post crop
52
+ def source_height
53
+ update_cache unless cache[:height]
54
+
55
+ cache[:height]
56
+ end
57
+
30
58
  private
31
59
 
60
+ # We exclude width and format from the cache name, since it isn't specific to them.
61
+ def cache
62
+ @cache ||= Cache::Generated.new("#{@source.base_name}-#{id}")
63
+ end
64
+
65
+ def update_cache
66
+ return if @source.missing
67
+
68
+ # Ensure it's generated:
69
+ image
70
+
71
+ cache[:width] = @source_dimensions[:width]
72
+ cache[:height] = @source_dimensions[:height]
73
+
74
+ cache.write
75
+ end
76
+
77
+ # Hash all inputs and truncate, so we know when they change without getting too long.
78
+ # /home/dave/my_blog/_site/generated/somefolder/myimage-100-1234abcde.jpg
79
+ # ^^^^^^^^^
80
+ def id
81
+ @id ||= Digest::MD5.hexdigest([@source.digest, @crop, @gravity, quality].join)[0..8]
82
+ end
83
+
84
+ # Post crop, before resizing and reformatting
32
85
  def image
33
- @image ||= Image.open(@source.name)
86
+ @image ||= open_image
34
87
  end
35
88
 
36
- def process_image
37
- image.combine_options do |i|
38
- i.resize "#{@width}x"
89
+ def open_image
90
+ image_base = Image.open(@source.name)
91
+ image_base.combine_options do |i|
39
92
  i.auto_orient
40
- i.strip
93
+ if @crop
94
+ i.gravity @gravity
95
+ i.crop @crop
96
+ end
41
97
  end
42
98
 
43
- image.format @format
44
- image.quality PictureTag.quality(@format)
99
+ @source_dimensions = { width: image_base.width, height: image_base.height }
100
+
101
+ image_base
45
102
  end
46
103
 
47
104
  def generate_image
@@ -50,20 +107,28 @@ module PictureTag
50
107
  write_image
51
108
  end
52
109
 
110
+ def quality
111
+ PictureTag.quality(@format)
112
+ end
113
+
114
+ def process_image
115
+ image.combine_options do |i|
116
+ i.resize "#{@width}x"
117
+ i.strip
118
+ end
119
+
120
+ image.format @format
121
+ image.quality quality
122
+ end
123
+
53
124
  def write_image
54
- check_dest_dir
125
+ FileUtils.mkdir_p(File.dirname(absolute_filename))
55
126
 
56
127
  image.write absolute_filename
57
128
 
58
129
  FileUtils.chmod(0o644, absolute_filename)
59
130
  end
60
131
 
61
- # Make sure destination directory exists
62
- def check_dest_dir
63
- dir = File.dirname absolute_filename
64
- FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
65
- end
66
-
67
132
  def process_format(format)
68
133
  if format.casecmp('original').zero?
69
134
  @source.ext