jekyll_picture_tag 1.10.2 → 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/docs/index.md +1 -1
- data/docs/presets.md +31 -1
- data/docs/releases.md +5 -0
- data/docs/usage.md +15 -1
- data/jekyll_picture_tag.gemspec +0 -1
- data/lib/jekyll_picture_tag.rb +1 -0
- 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/presets.yml +1 -0
- data/lib/jekyll_picture_tag/generated_image.rb +41 -62
- data/lib/jekyll_picture_tag/img_uri.rb +1 -0
- data/lib/jekyll_picture_tag/instructions/arg_splitter.rb +3 -2
- data/lib/jekyll_picture_tag/instructions/preset.rb +1 -0
- data/lib/jekyll_picture_tag/output_formats/basic.rb +7 -5
- 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 +1 -0
- data/lib/jekyll_picture_tag/source_image.rb +60 -44
- data/lib/jekyll_picture_tag/srcsets/basic.rb +10 -1
- data/lib/jekyll_picture_tag/version.rb +1 -1
- data/readme.md +5 -4
- metadata +6 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1fdaad2f56cc244f8bce4ffcf5689630fe71ec0b7e091d91e289a1dc7d6740d8
|
4
|
+
data.tar.gz: 971d590896ef6396a86c8ce6f6dd7fef46804443b4c2b76226e5e774dc5cd204
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77fa8b7e4b3db8839a988f0613b8e3b0257ff92f7e379db12bf9de1da3644acf7d6a6bfa0fb82b900fb71d2e6775d842d2187ec1e13617cf268098f98ad41e12
|
7
|
+
data.tar.gz: b9efeae7cff9bc5a962d9c076d735c00011ad231cbac264b232a29a6f4ec3af101d9f905a0cde61283b0b739b8d9388e92ccad7f600aacccc382c2845edbd71e
|
data/.rubocop.yml
CHANGED
data/docs/index.md
CHANGED
@@ -35,7 +35,7 @@ markup_presets:
|
|
35
35
|
default:
|
36
36
|
formats: [webp, original]
|
37
37
|
```
|
38
|
-
|
38
|
+
**Note:** Order matters! `[webp, jpg]` will offer the browser webp-images first. The browser will pick the *first* format it can work with. So if the order is reversed `[jpg, webp]` it will use the jpg image before the webp.
|
39
39
|
|
40
40
|
### Here's a more complete demonstration:
|
41
41
|
|
data/docs/presets.md
CHANGED
@@ -295,7 +295,37 @@ width (thumbnails and icons). To use a multiplier-based srcset, set `pixel_ratio
|
|
295
295
|
If you don't give a setting for a particular format it'll fall back to the `quality` setting
|
296
296
|
above, and if you don't set _that_ it'll default to 75.
|
297
297
|
|
298
|
-
* **
|
298
|
+
* **Width & Height attributes (Anti-Loading-Jank)**
|
299
|
+
|
300
|
+
_Format:_
|
301
|
+
|
302
|
+
```yml
|
303
|
+
dimension_attributes: true | false
|
304
|
+
```
|
305
|
+
|
306
|
+
_Example:_
|
307
|
+
|
308
|
+
```yml
|
309
|
+
dimension_attributes: true
|
310
|
+
```
|
311
|
+
|
312
|
+
_Default:_ `false`
|
313
|
+
|
314
|
+
Prevent page reflow (aka jank) while images are loading, by adding `width` and `height` attributes
|
315
|
+
to the `<img>` tag in the correct aspect ratio.
|
316
|
+
|
317
|
+
For an explanation of why and how you want to do this, [here](https://youtu.be/4-d_SoCHeWE) is a
|
318
|
+
great explanation.
|
319
|
+
|
320
|
+
Caveats:
|
321
|
+
* You need `width: 100%;` and `height: auto;` (or vice versa) set in CSS on the `<img>`
|
322
|
+
tags, or they will be stretched weirdly.
|
323
|
+
* This works on `<img>` tags and `<picture>` tags when offering images in multiple widths and
|
324
|
+
formats, but it does not work if you are using art direction (in other words, if you have
|
325
|
+
multiple source images). This is because these attributes can only be applied to the `<img>`
|
326
|
+
tag, of which there is exactly one.
|
327
|
+
|
328
|
+
* **Arbitrary HTML Attributes**
|
299
329
|
|
300
330
|
_Format:_
|
301
331
|
|
data/docs/releases.md
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
---
|
2
2
|
---
|
3
3
|
# Release History
|
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.
|
4
9
|
* 1.10.2 July 6, 2020
|
5
10
|
* Bugfix for fallback image files not actually getting generated
|
6
11
|
* 1.10.1 July 2, 2020
|
data/docs/usage.md
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
|
4
4
|
# How to use the Liquid Tag:
|
5
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
|
+
|
6
8
|
## Format:
|
7
9
|
|
8
10
|
{% raw %}
|
@@ -12,11 +14,22 @@
|
|
12
14
|
The only required argument is the base image. Line breaks and extra spaces are fine, and you can
|
13
15
|
use liquid variables anywhere.
|
14
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
|
+
|
15
26
|
## Examples:
|
16
27
|
|
17
28
|
{% raw %}
|
18
29
|
`{% picture example.jpg %}`
|
19
30
|
|
31
|
+
`{% picture {{ page.example_liquid_picture_var }} %}`
|
32
|
+
|
20
33
|
`{% picture thumbnail example.jpg 1:1 --alt Example Image %}`
|
21
34
|
|
22
35
|
`{% picture example.jpg 16:9 north --picture class="attribute-demo" %}`
|
@@ -47,7 +60,7 @@ Given in order:
|
|
47
60
|
|
48
61
|
Select a [markup preset]({{ site.baseurl }}/presets#markup-presets), or omit to use the `default` preset. Presets
|
49
62
|
are collections of settings that determine nearly everything about JPT's output, from the image
|
50
|
-
formats used to the exact format your markup will take.
|
63
|
+
formats used to the exact format your final HTML-markup will take.
|
51
64
|
|
52
65
|
- **Base Image** (Required)
|
53
66
|
|
@@ -141,3 +154,4 @@ Given in order:
|
|
141
154
|
|
142
155
|
`--parent` will be applied to the `<picture>` if present, otherwise the `<img>`; useful when
|
143
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
@@ -38,7 +38,6 @@ Gem::Specification.new do |spec|
|
|
38
38
|
spec.add_development_dependency 'solargraph'
|
39
39
|
|
40
40
|
spec.add_dependency 'addressable', '~> 2.6'
|
41
|
-
spec.add_dependency 'base32', '~> 0.3'
|
42
41
|
spec.add_dependency 'mime-types', '~> 3'
|
43
42
|
spec.add_dependency 'mini_magick', '~> 4'
|
44
43
|
spec.add_dependency 'objective_elements', '~> 1.1.2'
|
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
|
@@ -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,10 +1,10 @@
|
|
1
1
|
require 'mini_magick'
|
2
|
-
require 'base32'
|
3
2
|
|
4
3
|
module PictureTag
|
5
4
|
# Represents a generated image file.
|
6
5
|
class GeneratedImage
|
7
6
|
attr_reader :width, :format
|
7
|
+
|
8
8
|
include MiniMagick
|
9
9
|
|
10
10
|
def initialize(source_file:, width:, format:, crop: nil, gravity: '')
|
@@ -32,7 +32,7 @@ module PictureTag
|
|
32
32
|
# /home/dave/my_blog/_site/generated/somefolder/myimage-100-123abc.jpg
|
33
33
|
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
34
34
|
def name
|
35
|
-
|
35
|
+
@name ||= "#{@source.base_name}-#{@width}-#{id}.#{@format}"
|
36
36
|
end
|
37
37
|
|
38
38
|
# https://example.com/assets/images/myimage-100-123abc.jpg
|
@@ -41,75 +41,47 @@ module PictureTag
|
|
41
41
|
ImgURI.new(name).to_s
|
42
42
|
end
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
private
|
44
|
+
# Post crop
|
45
|
+
def source_width
|
46
|
+
update_cache unless cache[:width]
|
49
47
|
|
50
|
-
|
51
|
-
# ^^^^^^^^^^^^^^^^^^^^^^^
|
52
|
-
def name_left
|
53
|
-
"#{@source.base_name}-#{@width}-"
|
48
|
+
cache[:width]
|
54
49
|
end
|
55
50
|
|
56
|
-
#
|
57
|
-
|
58
|
-
|
59
|
-
guess_digest if !@source.digest_guess && PictureTag.fast_build?
|
60
|
-
|
61
|
-
@source.digest
|
62
|
-
end
|
51
|
+
# Post crop
|
52
|
+
def source_height
|
53
|
+
update_cache unless cache[:height]
|
63
54
|
|
64
|
-
|
65
|
-
# ^^^^
|
66
|
-
def name_right
|
67
|
-
crop_code + '.' + @format
|
55
|
+
cache[:height]
|
68
56
|
end
|
69
57
|
|
70
|
-
|
71
|
-
# base32 encoding scheme to pack more information into fewer characters,
|
72
|
-
# without dealing with various filesystem naming limitations that would crop
|
73
|
-
# up using base64 (such as NTFS being case insensitive).
|
74
|
-
def crop_code
|
75
|
-
return '' unless @crop
|
58
|
+
private
|
76
59
|
|
77
|
-
|
78
|
-
|
79
|
-
)
|
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}")
|
80
63
|
end
|
81
64
|
|
82
|
-
|
83
|
-
|
84
|
-
# source file, and if it exists we assume it's the right one.
|
85
|
-
def guess_digest
|
86
|
-
matches = dest_glob
|
87
|
-
return unless matches.length == 1
|
65
|
+
def update_cache
|
66
|
+
return if @source.missing
|
88
67
|
|
89
|
-
#
|
90
|
-
|
91
|
-
start = finish - 6
|
68
|
+
# Ensure it's generated:
|
69
|
+
image
|
92
70
|
|
93
|
-
|
94
|
-
|
95
|
-
end
|
71
|
+
cache[:width] = @source_dimensions[:width]
|
72
|
+
cache[:height] = @source_dimensions[:height]
|
96
73
|
|
97
|
-
|
98
|
-
def dest_glob
|
99
|
-
query = File.join(
|
100
|
-
PictureTag.dest_dir,
|
101
|
-
name_left + '?' * 6 + name_right
|
102
|
-
)
|
103
|
-
|
104
|
-
Dir.glob query
|
74
|
+
cache.write
|
105
75
|
end
|
106
76
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
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]
|
111
82
|
end
|
112
83
|
|
84
|
+
# Post crop, before resizing and reformatting
|
113
85
|
def image
|
114
86
|
@image ||= open_image
|
115
87
|
end
|
@@ -124,9 +96,21 @@ module PictureTag
|
|
124
96
|
end
|
125
97
|
end
|
126
98
|
|
99
|
+
@source_dimensions = { width: image_base.width, height: image_base.height }
|
100
|
+
|
127
101
|
image_base
|
128
102
|
end
|
129
103
|
|
104
|
+
def generate_image
|
105
|
+
puts 'Generating new image file: ' + name
|
106
|
+
process_image
|
107
|
+
write_image
|
108
|
+
end
|
109
|
+
|
110
|
+
def quality
|
111
|
+
PictureTag.quality(@format)
|
112
|
+
end
|
113
|
+
|
130
114
|
def process_image
|
131
115
|
image.combine_options do |i|
|
132
116
|
i.resize "#{@width}x"
|
@@ -134,22 +118,17 @@ module PictureTag
|
|
134
118
|
end
|
135
119
|
|
136
120
|
image.format @format
|
137
|
-
image.quality
|
121
|
+
image.quality quality
|
138
122
|
end
|
139
123
|
|
140
124
|
def write_image
|
141
|
-
|
142
|
-
FileUtils.mkdir_p(dest_dir) unless Dir.exist?(dest_dir)
|
125
|
+
FileUtils.mkdir_p(File.dirname(absolute_filename))
|
143
126
|
|
144
127
|
image.write absolute_filename
|
145
128
|
|
146
129
|
FileUtils.chmod(0o644, absolute_filename)
|
147
130
|
end
|
148
131
|
|
149
|
-
def dest_dir
|
150
|
-
File.dirname absolute_filename
|
151
|
-
end
|
152
|
-
|
153
132
|
def process_format(format)
|
154
133
|
if format.casecmp('original').zero?
|
155
134
|
@source.ext
|
@@ -6,6 +6,10 @@ module PictureTag
|
|
6
6
|
class Basic
|
7
7
|
include ObjectiveElements
|
8
8
|
|
9
|
+
def to_s
|
10
|
+
wrap(base_markup).to_s
|
11
|
+
end
|
12
|
+
|
9
13
|
# Used for both the fallback image, and for the complete markup.
|
10
14
|
def build_base_img
|
11
15
|
img = SingleTag.new 'img'
|
@@ -23,10 +27,6 @@ module PictureTag
|
|
23
27
|
img
|
24
28
|
end
|
25
29
|
|
26
|
-
def to_s
|
27
|
-
wrap(base_markup).to_s
|
28
|
-
end
|
29
|
-
|
30
30
|
private
|
31
31
|
|
32
32
|
# Handles various wrappers around basic markup
|
@@ -86,6 +86,8 @@ module PictureTag
|
|
86
86
|
image
|
87
87
|
end
|
88
88
|
|
89
|
+
# It's only a candidate, because we don't know if the fallback width
|
90
|
+
# setting is larger than the source file.
|
89
91
|
def fallback_candidate
|
90
92
|
@fallback_candidate ||= GeneratedImage.new(
|
91
93
|
source_file: PictureTag.source_images.first,
|
@@ -119,7 +121,7 @@ module PictureTag
|
|
119
121
|
|
120
122
|
def source_width
|
121
123
|
if PictureTag.crop
|
122
|
-
fallback_candidate.
|
124
|
+
fallback_candidate.source_width
|
123
125
|
else
|
124
126
|
source.width
|
125
127
|
end
|
@@ -3,6 +3,8 @@ module PictureTag
|
|
3
3
|
# Represents a bare <img> tag with a srcset attribute.
|
4
4
|
# Used when <picture> is unnecessary.
|
5
5
|
class Img < Basic
|
6
|
+
private
|
7
|
+
|
6
8
|
def srcset
|
7
9
|
@srcset ||= build_srcset(
|
8
10
|
PictureTag.source_images.first, PictureTag.formats.first
|
@@ -17,8 +19,17 @@ module PictureTag
|
|
17
19
|
|
18
20
|
img.attributes << PictureTag.html_attributes['parent']
|
19
21
|
|
22
|
+
add_dimensions(img, srcset)
|
23
|
+
|
20
24
|
img
|
21
25
|
end
|
26
|
+
|
27
|
+
def add_dimensions(img, srcset)
|
28
|
+
return unless PictureTag.preset['dimension_attributes']
|
29
|
+
|
30
|
+
img.width = srcset.width_attribute
|
31
|
+
img.height = srcset.height_attribute
|
32
|
+
end
|
22
33
|
end
|
23
34
|
end
|
24
35
|
end
|
@@ -3,7 +3,13 @@ module PictureTag
|
|
3
3
|
# Represents a <picture> tag, enclosing at least 2 <source> tags and an
|
4
4
|
# <img> tag.
|
5
5
|
class Picture < Basic
|
6
|
+
private
|
7
|
+
|
6
8
|
def srcsets
|
9
|
+
@srcsets ||= build_srcsets
|
10
|
+
end
|
11
|
+
|
12
|
+
def build_srcsets
|
7
13
|
formats = PictureTag.formats
|
8
14
|
# Source images are provided in reverse order and must be flipped:
|
9
15
|
images = PictureTag.source_images.reverse
|
@@ -37,6 +43,22 @@ module PictureTag
|
|
37
43
|
source
|
38
44
|
end
|
39
45
|
|
46
|
+
def build_base_img
|
47
|
+
img = super
|
48
|
+
|
49
|
+
# Only add source dimensions if there is a single source image.
|
50
|
+
# Currently you can't use both art direction and intrinsic image sizes.
|
51
|
+
if PictureTag.preset['dimension_attributes'] &&
|
52
|
+
PictureTag.source_images.length == 1
|
53
|
+
img.attributes << {
|
54
|
+
width: srcsets.first.width_attribute,
|
55
|
+
height: srcsets.first.height_attribute
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
img
|
60
|
+
end
|
61
|
+
|
40
62
|
def base_markup
|
41
63
|
picture = DoubleTag.new(
|
42
64
|
'picture',
|
@@ -3,84 +3,100 @@ module PictureTag
|
|
3
3
|
# advantage by storing expensive file reads and writes in instance variables,
|
4
4
|
# to be reused by many different generated images.
|
5
5
|
class SourceImage
|
6
|
-
attr_reader :
|
7
|
-
|
6
|
+
attr_reader :shortname, :missing, :media_preset
|
7
|
+
|
8
8
|
include MiniMagick
|
9
9
|
|
10
10
|
def initialize(relative_filename, media_preset = nil)
|
11
|
+
# /home/dave/my_blog/assets/images/somefolder/myimage.jpg
|
12
|
+
# ^^^^^^^^^^^^^^^^^^^^^^
|
11
13
|
@shortname = relative_filename
|
12
|
-
@name = grab_file relative_filename
|
13
14
|
@media_preset = media_preset
|
15
|
+
|
16
|
+
@missing = missing?
|
17
|
+
check_cache
|
18
|
+
end
|
19
|
+
|
20
|
+
def digest
|
21
|
+
@digest ||= cache[:digest] || ''
|
14
22
|
end
|
15
23
|
|
16
24
|
def width
|
17
|
-
@width ||=
|
18
|
-
999_999
|
19
|
-
else
|
20
|
-
image.width
|
21
|
-
end
|
25
|
+
@width ||= cache[:width] || 999_999
|
22
26
|
end
|
23
27
|
|
24
|
-
def
|
25
|
-
@
|
26
|
-
'x' * 6
|
27
|
-
elsif PictureTag.fast_build? && @digest_guess
|
28
|
-
# Digest guess will be handed off to this class by the first
|
29
|
-
# generated image which needs it (via attr_accessor).
|
30
|
-
@digest_guess
|
31
|
-
else
|
32
|
-
Digest::MD5.hexdigest(File.read(@name))[0..5]
|
33
|
-
end
|
28
|
+
def height
|
29
|
+
@height ||= cache[:height] || 999_999
|
34
30
|
end
|
35
31
|
|
36
|
-
#
|
32
|
+
# /home/dave/my_blog/assets/images/somefolder/myimage.jpg
|
33
|
+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
34
|
+
def name
|
35
|
+
@name ||= File.join(PictureTag.source_dir, @shortname)
|
36
|
+
end
|
37
|
+
|
38
|
+
# /home/dave/my_blog/assets/images/somefolder/myimage.jpg
|
39
|
+
# ^^^^^^^^^^^^^^^^^^
|
37
40
|
def base_name
|
38
41
|
@shortname.delete_suffix File.extname(@shortname)
|
39
42
|
end
|
40
43
|
|
41
|
-
#
|
44
|
+
# /home/dave/my_blog/assets/images/somefolder/myimage.jpg
|
45
|
+
# ^^^
|
42
46
|
def ext
|
43
|
-
|
44
|
-
@ext ||= File.extname(@name)[1..-1].downcase
|
47
|
+
@ext ||= File.extname(name)[1..-1].downcase
|
45
48
|
end
|
46
49
|
|
47
50
|
private
|
48
51
|
|
49
|
-
def
|
50
|
-
@
|
52
|
+
def cache
|
53
|
+
@cache ||= Cache::Source.new(@shortname)
|
51
54
|
end
|
52
55
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
if File.exist? source_name
|
58
|
-
@missing = false
|
56
|
+
def missing?
|
57
|
+
if File.exist? name
|
58
|
+
false
|
59
59
|
|
60
60
|
elsif PictureTag.continue_on_missing?
|
61
|
-
|
62
|
-
|
61
|
+
Utils.warning(missing_image_warning)
|
62
|
+
true
|
63
63
|
|
64
64
|
else
|
65
|
-
raise ArgumentError, missing_image_error
|
65
|
+
raise ArgumentError, missing_image_error
|
66
66
|
end
|
67
|
+
end
|
67
68
|
|
68
|
-
|
69
|
+
def check_cache
|
70
|
+
return if @missing
|
71
|
+
return if cache[:digest] && PictureTag.fast_build?
|
72
|
+
|
73
|
+
update_cache if source_digest != cache[:digest]
|
69
74
|
end
|
70
75
|
|
71
|
-
def
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
+
def update_cache
|
77
|
+
cache[:digest] = source_digest
|
78
|
+
cache[:width] = image.width
|
79
|
+
cache[:height] = image.height
|
80
|
+
|
81
|
+
cache.write
|
82
|
+
end
|
83
|
+
|
84
|
+
def image
|
85
|
+
@image ||= Image.open(name)
|
86
|
+
end
|
87
|
+
|
88
|
+
def source_digest
|
89
|
+
@source_digest ||= Digest::MD5.hexdigest(File.read(name))
|
90
|
+
end
|
91
|
+
|
92
|
+
def missing_image_warning
|
93
|
+
"JPT Could not find #{name}. Your site will have broken images. Continuing."
|
76
94
|
end
|
77
95
|
|
78
|
-
def missing_image_error
|
96
|
+
def missing_image_error
|
79
97
|
<<~HEREDOC
|
80
|
-
|
81
|
-
|
82
|
-
true" in "_config.yml". This setting can also accept a jekyll build
|
83
|
-
environment, or an array of environments.
|
98
|
+
Could not find #{name}. You can force the build to continue anyway by
|
99
|
+
setting "picture: ignore_missing_images: true" in "_config.yml".
|
84
100
|
HEREDOC
|
85
101
|
end
|
86
102
|
end
|
@@ -23,6 +23,7 @@ module PictureTag
|
|
23
23
|
@format ||= files.first.format
|
24
24
|
end
|
25
25
|
|
26
|
+
# GeneratedImage class
|
26
27
|
def files
|
27
28
|
@files ||= build_files
|
28
29
|
end
|
@@ -51,6 +52,14 @@ module PictureTag
|
|
51
52
|
"(#{PictureTag.media_presets[@media]})"
|
52
53
|
end
|
53
54
|
|
55
|
+
def width_attribute
|
56
|
+
files.first.source_width.to_s
|
57
|
+
end
|
58
|
+
|
59
|
+
def height_attribute
|
60
|
+
files.first.source_height.to_s
|
61
|
+
end
|
62
|
+
|
54
63
|
private
|
55
64
|
|
56
65
|
def build_files
|
@@ -78,7 +87,7 @@ module PictureTag
|
|
78
87
|
|
79
88
|
def source_width
|
80
89
|
@source_width ||= if PictureTag.crop(@media)
|
81
|
-
target_files.first.
|
90
|
+
target_files.first.source_width
|
82
91
|
else
|
83
92
|
@source_image.width
|
84
93
|
end
|
data/readme.md
CHANGED
@@ -43,14 +43,15 @@ https://rbuchberger.github.io/jekyll_picture_tag/releases
|
|
43
43
|
|
44
44
|
Latest versions:
|
45
45
|
|
46
|
-
* 1.10.0 May 11, 2020
|
47
|
-
* **Image Cropping support!** access the power of ImageMagick's `crop` function.
|
48
|
-
* Don't issue a warning when `default` preset is not found.
|
49
|
-
* Documentation improvements
|
50
46
|
* 1.10.1 July 2, 2020
|
51
47
|
* Bugfix for erroneously regenerated images
|
52
48
|
* 1.10.2 July 6, 2020
|
53
49
|
* Bugfix for fallback image files not actually getting generated
|
50
|
+
* 1.11.0 July 27, 2020
|
51
|
+
* **Width and height attribute support!** Begone, page reflow.
|
52
|
+
* Cache image information between builds
|
53
|
+
* Change image naming format. This update will trigger all images to be regenerated, so you may
|
54
|
+
want to delete your generated images folder beforehand.
|
54
55
|
|
55
56
|
## Help Wanted
|
56
57
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll_picture_tag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Wierzbowski
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2020-07-
|
13
|
+
date: 2020-07-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -152,20 +152,6 @@ dependencies:
|
|
152
152
|
- - "~>"
|
153
153
|
- !ruby/object:Gem::Version
|
154
154
|
version: '2.6'
|
155
|
-
- !ruby/object:Gem::Dependency
|
156
|
-
name: base32
|
157
|
-
requirement: !ruby/object:Gem::Requirement
|
158
|
-
requirements:
|
159
|
-
- - "~>"
|
160
|
-
- !ruby/object:Gem::Version
|
161
|
-
version: '0.3'
|
162
|
-
type: :runtime
|
163
|
-
prerelease: false
|
164
|
-
version_requirements: !ruby/object:Gem::Requirement
|
165
|
-
requirements:
|
166
|
-
- - "~>"
|
167
|
-
- !ruby/object:Gem::Version
|
168
|
-
version: '0.3'
|
169
155
|
- !ruby/object:Gem::Dependency
|
170
156
|
name: mime-types
|
171
157
|
requirement: !ruby/object:Gem::Requirement
|
@@ -263,6 +249,10 @@ files:
|
|
263
249
|
- jekyll_picture_tag.gemspec
|
264
250
|
- lib/jekyll-picture-tag.rb
|
265
251
|
- lib/jekyll_picture_tag.rb
|
252
|
+
- lib/jekyll_picture_tag/cache.rb
|
253
|
+
- lib/jekyll_picture_tag/cache/base.rb
|
254
|
+
- lib/jekyll_picture_tag/cache/generated.rb
|
255
|
+
- lib/jekyll_picture_tag/cache/source.rb
|
266
256
|
- lib/jekyll_picture_tag/defaults/global.yml
|
267
257
|
- lib/jekyll_picture_tag/defaults/presets.yml
|
268
258
|
- lib/jekyll_picture_tag/generated_image.rb
|