jekyll_picture_tag 1.10.2 → 1.11.0
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/.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
|