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.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/.travis.yml +4 -7
- data/Dockerfile +9 -0
- data/docs/Gemfile.lock +183 -88
- data/docs/contributing.md +50 -16
- data/docs/example_presets.md +1 -1
- data/docs/global_configuration.md +55 -2
- data/docs/index.md +27 -21
- data/docs/installation.md +22 -7
- data/docs/presets.md +137 -55
- data/docs/releases.md +20 -1
- data/docs/usage.md +83 -39
- data/jekyll_picture_tag.gemspec +1 -1
- data/lib/jekyll_picture_tag.rb +28 -10
- data/lib/jekyll_picture_tag/cache.rb +3 -0
- data/lib/jekyll_picture_tag/cache/base.rb +59 -0
- data/lib/jekyll_picture_tag/cache/generated.rb +20 -0
- data/lib/jekyll_picture_tag/cache/source.rb +19 -0
- data/lib/jekyll_picture_tag/defaults/global.yml +2 -0
- data/lib/jekyll_picture_tag/defaults/presets.yml +2 -0
- data/lib/jekyll_picture_tag/generated_image.rb +85 -20
- data/lib/jekyll_picture_tag/img_uri.rb +1 -0
- data/lib/jekyll_picture_tag/instructions.rb +1 -0
- data/lib/jekyll_picture_tag/instructions/arg_splitter.rb +69 -0
- data/lib/jekyll_picture_tag/instructions/configuration.rb +47 -11
- data/lib/jekyll_picture_tag/instructions/preset.rb +35 -14
- data/lib/jekyll_picture_tag/instructions/set.rb +18 -8
- data/lib/jekyll_picture_tag/instructions/tag_parser.rb +59 -69
- data/lib/jekyll_picture_tag/output_formats/basic.rb +42 -11
- data/lib/jekyll_picture_tag/output_formats/img.rb +11 -0
- data/lib/jekyll_picture_tag/output_formats/picture.rb +22 -0
- data/lib/jekyll_picture_tag/router.rb +17 -0
- data/lib/jekyll_picture_tag/source_image.rb +60 -39
- data/lib/jekyll_picture_tag/srcsets/basic.rb +54 -19
- data/lib/jekyll_picture_tag/srcsets/pixel_ratio.rb +1 -3
- data/lib/jekyll_picture_tag/srcsets/width.rb +1 -1
- data/lib/jekyll_picture_tag/utils.rb +18 -0
- data/lib/jekyll_picture_tag/version.rb +1 -1
- data/readme.md +40 -16
- metadata +14 -8
data/docs/releases.md
CHANGED
@@ -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
|
data/docs/usage.md
CHANGED
@@ -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] (
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
121
|
+
- **`--link`**
|
122
|
+
|
123
|
+
_Format:_ `--link (some url)`
|
79
124
|
|
80
|
-
|
125
|
+
_Examples_: `--link https://example.com`, `--link /blog/some_post/`
|
81
126
|
|
82
|
-
|
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
|
-
|
85
|
-
|
130
|
+
**Note**: If you get either mangled HTML or extra {::nomarkdown} tags when using this, read
|
131
|
+
[here]({{ site.baseurl }}/notes).
|
86
132
|
|
87
|
-
|
88
|
-
[here]({{ site.baseurl }}/notes).
|
133
|
+
- **`--alt`**
|
89
134
|
|
90
|
-
|
91
|
-
|
92
|
-
*Format:* `--alt (alt text)`
|
135
|
+
_Format:_ `--alt (alt text)`
|
93
136
|
|
94
|
-
|
137
|
+
_Example:_ `--alt Here is my alt text!`
|
95
138
|
|
96
139
|
Convenience shortcut for `--img alt="..."`
|
97
|
-
|
98
|
-
* **`--(element)`**
|
99
140
|
|
100
|
-
|
141
|
+
- **`--(element)`**
|
142
|
+
|
143
|
+
_Format:_ `--(picture|img|source|a|parent) (Standard HTML attributes)`
|
101
144
|
|
102
|
-
|
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
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
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).
|
data/jekyll_picture_tag.gemspec
CHANGED
@@ -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.
|
43
|
+
spec.add_dependency 'objective_elements', '~> 1.1.2'
|
44
44
|
|
45
45
|
spec.add_runtime_dependency 'jekyll', '< 5'
|
46
46
|
end
|
data/lib/jekyll_picture_tag.rb
CHANGED
@@ -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://
|
22
|
-
# Documentation: https://github.
|
23
|
-
# Issues: https://github.com/rbuchberger/jekyll_picture_tag/
|
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
|
-
|
54
|
-
|
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
|
-
#
|
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,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
|
@@ -1,47 +1,104 @@
|
|
1
1
|
require 'mini_magick'
|
2
2
|
|
3
3
|
module PictureTag
|
4
|
-
#
|
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
|
-
|
18
|
+
def exists?
|
19
|
+
File.exist?(absolute_filename)
|
16
20
|
end
|
17
21
|
|
18
|
-
def
|
19
|
-
|
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 ||=
|
86
|
+
@image ||= open_image
|
34
87
|
end
|
35
88
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
89
|
+
def open_image
|
90
|
+
image_base = Image.open(@source.name)
|
91
|
+
image_base.combine_options do |i|
|
39
92
|
i.auto_orient
|
40
|
-
|
93
|
+
if @crop
|
94
|
+
i.gravity @gravity
|
95
|
+
i.crop @crop
|
96
|
+
end
|
41
97
|
end
|
42
98
|
|
43
|
-
|
44
|
-
|
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
|
-
|
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
|