jekyll_picture_tag 1.8.0 → 1.9.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/docs/global_configuration.md +55 -2
- data/docs/releases.md +7 -0
- data/lib/jekyll_picture_tag.rb +27 -10
- data/lib/jekyll_picture_tag/defaults/global.yml +2 -0
- data/lib/jekyll_picture_tag/generated_image.rb +67 -13
- data/lib/jekyll_picture_tag/instructions/configuration.rb +46 -10
- data/lib/jekyll_picture_tag/output_formats/basic.rb +13 -1
- data/lib/jekyll_picture_tag/router.rb +8 -0
- data/lib/jekyll_picture_tag/source_image.rb +6 -1
- data/lib/jekyll_picture_tag/srcsets/basic.rb +31 -18
- 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/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa7bf95094ae98a78cd4ff1d40fd70d74378590d68a39273300ba216280a9794
|
4
|
+
data.tar.gz: 9e552372626ff7f1a54b8bacc902112b7cfd9c65ce01c6d8957fd411ff88a1ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a7a4c78be31edc35758dc6fa5f5f90a0ba0bcc5801f3ebf570b13ba649d04f4b2df88472c8b583439b9e3888537e26f9eb3678a364abe5ef6d299a65b5fe216
|
7
|
+
data.tar.gz: aab45d2868253d91d82e8ce63b0fab117a394427bc6b4a5248cf395b5a29e29e9bddbcfcdb8e4a365e087d3bde93a06bedfc16a8c37b9bef71aac2479d4fd84f
|
@@ -65,7 +65,12 @@ picture:
|
|
65
65
|
|
66
66
|
*Default:* `false`
|
67
67
|
|
68
|
-
Normally, JPT will raise an error if a source image is missing, causing the entire site build to
|
68
|
+
Normally, JPT will raise an error if a source image is missing, causing the entire site build to
|
69
|
+
fail. This setting allows you to bypass this behavior and continue the build, either for certain
|
70
|
+
build environments or all the time. I highly encourage you to set this to `development`, and set
|
71
|
+
the jekyll build environment to `production` when you build for production so you don't shoot
|
72
|
+
yourself in the foot (publish a site with broken images). You can read more about Jekyll
|
73
|
+
environments [here](https://jekyllrb.com/docs/configuration/environments/).
|
69
74
|
|
70
75
|
* **Use Relative Urls**
|
71
76
|
|
@@ -111,10 +116,58 @@ picture:
|
|
111
116
|
|
112
117
|
*Example:* `nomarkdown: false`
|
113
118
|
|
114
|
-
*Default
|
119
|
+
*Default:* `true`
|
115
120
|
|
116
121
|
Whether or not to surround j-p-t's output with a `{::nomarkdown}..{:/nomarkdown}` block when called
|
117
122
|
from within a markdown file.
|
118
123
|
|
119
124
|
This setting is overridden by the same setting in a preset. See [the notes]({{ site.baseurl
|
120
125
|
}}/notes) for more detailed information.
|
126
|
+
|
127
|
+
* **Fast Build**
|
128
|
+
|
129
|
+
*Format:* `fast_build: (true|false|environment|array of environments)`
|
130
|
+
|
131
|
+
*Examples:*
|
132
|
+
|
133
|
+
- `fast_build: true`
|
134
|
+
|
135
|
+
- `fast_build: development`
|
136
|
+
|
137
|
+
- `fast_build: [development, staging]`
|
138
|
+
|
139
|
+
*Default:* `false`
|
140
|
+
|
141
|
+
Makes a tradeoff: Speeds repeated build times for sites with many images, by assuming that the
|
142
|
+
filename alone is enough to uniquely identify a source image. This doesn't speed up image
|
143
|
+
generation, just detection of whether or not it's necessary.
|
144
|
+
|
145
|
+
Ordinarily, JPT generates an MD5 hash for every source image, every site build. This ensures that
|
146
|
+
if you replace one image with another, but keep the filename the same, JPT will correctly generate
|
147
|
+
images for the new file. If you have many large images and/or limited hardware, this can take some
|
148
|
+
time and make the development process painful. Enable this setting to skip MD5 hash checking on
|
149
|
+
existing generated images (most of the time), and just assume that if the filename, format, and
|
150
|
+
width match then it's the right one. If there are multiple possible matches (resulting from
|
151
|
+
leftover generated images from previous filename replacements), it'll compute a hash instead of
|
152
|
+
guessing randomly.
|
153
|
+
|
154
|
+
* **Disable Jekyll Picture Tag**
|
155
|
+
|
156
|
+
*Format:* `disabled: (true|false|environment|array of environments)`
|
157
|
+
|
158
|
+
*Examples:*
|
159
|
+
|
160
|
+
- `disabled: true`
|
161
|
+
|
162
|
+
- `disabled: development`
|
163
|
+
|
164
|
+
- `disabled: [development, staging]`
|
165
|
+
|
166
|
+
*Default:* `false`
|
167
|
+
|
168
|
+
Disable image and markup generation entirely. Useful for debugging, or to speed up site builds
|
169
|
+
when you're working on something else.
|
170
|
+
|
171
|
+
Hint: If you're going to toggle this on and off frequently, you might just use an environment
|
172
|
+
variable. Set this to something like `nopics`, and then start the Jekyll server with something
|
173
|
+
like `JEKYLL_ENV=nopics bundle exec jekyll serve` when you don't want image generation.
|
data/docs/releases.md
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
---
|
3
3
|
# Release History
|
4
4
|
|
5
|
+
* 1.9.0 Feb 2, 2020
|
6
|
+
* Add `fast_build` global setting
|
7
|
+
* Add `disabled` global setting
|
8
|
+
* Reduce unnecessary disk IO; sites with many source images should see build times improve when
|
9
|
+
no new images need to be generated.
|
10
|
+
* Add support for empty attributes; specifically so best-practice for decorative images (`alt=""`)
|
11
|
+
is possible.
|
5
12
|
* 1.8.0 Nov 25, 2019
|
6
13
|
* Add `data_sizes` setting for the `data_` family of output formats.
|
7
14
|
* 1.7.1 Nov 14, 2019
|
data/lib/jekyll_picture_tag.rb
CHANGED
@@ -18,9 +18,9 @@ require_relative 'jekyll_picture_tag/router'
|
|
18
18
|
#
|
19
19
|
# Description: Easy responsive images for Jekyll.
|
20
20
|
#
|
21
|
-
# Download: https://
|
22
|
-
# Documentation: https://github.
|
23
|
-
# Issues: https://github.com/rbuchberger/jekyll_picture_tag/
|
21
|
+
# Download: https://rubygems.org/gems/jekyll_picture_tag
|
22
|
+
# Documentation: https://rbuchberger.github.io/jekyll_picture_tag/
|
23
|
+
# Issues: https://github.com/rbuchberger/jekyll_picture_tag/
|
24
24
|
#
|
25
25
|
# Syntax:
|
26
26
|
# {% picture [preset] img.jpg [media_query: alt-img.jpg] [attributes] %}
|
@@ -39,30 +39,47 @@ require_relative 'jekyll_picture_tag/router'
|
|
39
39
|
#
|
40
40
|
# See the documentation for full configuration and usage instructions.
|
41
41
|
module PictureTag
|
42
|
+
# The router module is important. If you're looking for the actual code which
|
43
|
+
# handles a `PictureTag.(some method)`, start there.
|
42
44
|
extend Router
|
45
|
+
|
43
46
|
ROOT_PATH = __dir__
|
44
47
|
|
45
48
|
# This is the actual liquid tag, which provides the interface with Jekyll.
|
46
49
|
class Picture < Liquid::Tag
|
50
|
+
# First jekyll initializes our class with a few arguments, of which we only
|
51
|
+
# care about the params (arguments passed to the liquid tag). Jekyll makes
|
52
|
+
# no attempt to parse them; they're given as a string.
|
47
53
|
def initialize(tag_name, raw_params, tokens)
|
48
54
|
@raw_params = raw_params
|
49
55
|
super
|
50
56
|
end
|
51
57
|
|
58
|
+
# Then jekyll calls the 'render' method and passes it a mostly undocumented
|
59
|
+
# context object, which appears to hold the entire site including its
|
60
|
+
# configuration and the parsed _data dir.
|
52
61
|
def render(context)
|
53
|
-
|
54
|
-
|
62
|
+
setup(context)
|
63
|
+
|
64
|
+
if PictureTag.disabled?
|
65
|
+
''
|
66
|
+
else
|
67
|
+
PictureTag.output_class.new.to_s
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def setup(context)
|
55
74
|
PictureTag.context = context
|
56
75
|
|
57
|
-
#
|
76
|
+
# Now that we have both the tag parameters and the context object, we can
|
77
|
+
# build our instruction set.
|
58
78
|
PictureTag.instructions = Instructions::Set.new(@raw_params)
|
59
79
|
|
60
80
|
# We need to explicitly prevent jekyll from overwriting our generated
|
61
|
-
# files:
|
81
|
+
# image files:
|
62
82
|
Utils.keep_files
|
63
|
-
|
64
|
-
# Return a string:
|
65
|
-
PictureTag.output_class.new.to_s
|
66
83
|
end
|
67
84
|
end
|
68
85
|
end
|
@@ -1,8 +1,7 @@
|
|
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
|
8
7
|
include MiniMagick
|
@@ -11,28 +10,90 @@ module PictureTag
|
|
11
10
|
@source = source_file
|
12
11
|
@width = width
|
13
12
|
@format = process_format format
|
13
|
+
end
|
14
14
|
|
15
|
-
|
15
|
+
def exists?
|
16
|
+
File.exist?(absolute_filename)
|
16
17
|
end
|
17
18
|
|
18
|
-
def
|
19
|
-
|
19
|
+
def generate
|
20
|
+
generate_image unless @source.missing || exists?
|
20
21
|
end
|
21
22
|
|
23
|
+
# /home/dave/my_blog/_site/generated/somefolder/myimage-100-123abc.jpg
|
24
|
+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
22
25
|
def absolute_filename
|
23
26
|
@absolute_filename ||= File.join(PictureTag.dest_dir, name)
|
24
27
|
end
|
25
28
|
|
29
|
+
# /home/dave/my_blog/_site/generated/somefolder/myimage-100-123abc.jpg
|
30
|
+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
31
|
+
def name
|
32
|
+
name_left + digest + name_right
|
33
|
+
end
|
34
|
+
|
35
|
+
# https://example.com/assets/images/myimage-100-123abc.jpg
|
36
|
+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
26
37
|
def uri
|
27
38
|
ImgURI.new(name).to_s
|
28
39
|
end
|
29
40
|
|
30
41
|
private
|
31
42
|
|
43
|
+
# /home/dave/my_blog/_site/generated/somefolder/myimage-100-123abc.jpg
|
44
|
+
# ^^^^^^^^^^^^^^^^^^^^^^^
|
45
|
+
def name_left
|
46
|
+
"#{@source.base_name}-#{@width}-"
|
47
|
+
end
|
48
|
+
|
49
|
+
# /home/dave/my_blog/_site/generated/somefolder/myimage-100-123abc.jpg
|
50
|
+
# ^^^^^^
|
51
|
+
def digest
|
52
|
+
guess_digest if !@source.digest_guess && PictureTag.fast_build?
|
53
|
+
|
54
|
+
@source.digest
|
55
|
+
end
|
56
|
+
|
57
|
+
# /home/dave/my_blog/_site/generated/somefolder/myimage-100-123abc.jpg
|
58
|
+
# ^^^^
|
59
|
+
def name_right
|
60
|
+
'.' + @format
|
61
|
+
end
|
62
|
+
|
63
|
+
# Used for the fast build option: look for a file which matches everything
|
64
|
+
# we know about the destination file without calculating a digest on the
|
65
|
+
# source file, and if it exists we assume it's the right one.
|
66
|
+
def guess_digest
|
67
|
+
matches = dest_glob
|
68
|
+
return unless matches.length == 1
|
69
|
+
|
70
|
+
# Start and finish of the destination image's hash value
|
71
|
+
finish = -name_right.length
|
72
|
+
start = finish - 6
|
73
|
+
|
74
|
+
# The source image keeps track of this guess, so we hand it off:
|
75
|
+
@source.digest_guess = matches.first[start...finish]
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns a list of images which are probably correct.
|
79
|
+
def dest_glob
|
80
|
+
Dir.glob File.join(PictureTag.dest_dir, name_left + '?' * 6 + name_right)
|
81
|
+
end
|
82
|
+
|
32
83
|
def image
|
33
84
|
@image ||= Image.open(@source.name)
|
34
85
|
end
|
35
86
|
|
87
|
+
def dest_dir
|
88
|
+
File.dirname absolute_filename
|
89
|
+
end
|
90
|
+
|
91
|
+
def generate_image
|
92
|
+
puts 'Generating new image file: ' + name
|
93
|
+
process_image
|
94
|
+
write_image
|
95
|
+
end
|
96
|
+
|
36
97
|
def process_image
|
37
98
|
image.combine_options do |i|
|
38
99
|
i.resize "#{@width}x"
|
@@ -44,12 +105,6 @@ module PictureTag
|
|
44
105
|
image.quality PictureTag.quality(@format)
|
45
106
|
end
|
46
107
|
|
47
|
-
def generate_image
|
48
|
-
puts 'Generating new image file: ' + name
|
49
|
-
process_image
|
50
|
-
write_image
|
51
|
-
end
|
52
|
-
|
53
108
|
def write_image
|
54
109
|
check_dest_dir
|
55
110
|
|
@@ -60,8 +115,7 @@ module PictureTag
|
|
60
115
|
|
61
116
|
# Make sure destination directory exists
|
62
117
|
def check_dest_dir
|
63
|
-
|
64
|
-
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
|
118
|
+
FileUtils.mkdir_p(dest_dir) unless Dir.exist?(dest_dir)
|
65
119
|
end
|
66
120
|
|
67
121
|
def process_format(format)
|
@@ -38,28 +38,64 @@ module PictureTag
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def continue_on_missing?
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
setting
|
50
|
-
end
|
41
|
+
env_check pconfig['ignore_missing_images']
|
42
|
+
rescue ArgumentError
|
43
|
+
raise ArgumentError,
|
44
|
+
<<~HEREDOC
|
45
|
+
continue_on_missing setting invalid. Must be either a boolean
|
46
|
+
(true/false), an environment name, or an array of environment
|
47
|
+
names.
|
48
|
+
HEREDOC
|
51
49
|
end
|
52
50
|
|
53
51
|
def cdn?
|
54
52
|
pconfig['cdn_url'] && pconfig['cdn_environments'].include?(jekyll_env)
|
55
53
|
end
|
56
54
|
|
55
|
+
def disabled?
|
56
|
+
env_check pconfig['disabled']
|
57
|
+
rescue ArgumentError
|
58
|
+
raise ArgumentError,
|
59
|
+
<<~HEREDOC
|
60
|
+
"disabled" setting invalid. Must be either a boolean
|
61
|
+
(true/false), an environment name, or an array of environment
|
62
|
+
names.
|
63
|
+
HEREDOC
|
64
|
+
end
|
65
|
+
|
66
|
+
def fast_build?
|
67
|
+
env_check pconfig['fast_build']
|
68
|
+
rescue ArgumentError
|
69
|
+
raise ArgumentError,
|
70
|
+
<<~HEREDOC
|
71
|
+
"fast_build" setting invalid. Must be either a boolean
|
72
|
+
(true/false), an environment name, or an array of environment
|
73
|
+
names.
|
74
|
+
HEREDOC
|
75
|
+
end
|
76
|
+
|
57
77
|
private
|
58
78
|
|
59
79
|
def content
|
60
80
|
@content ||= setting_merge(defaults, PictureTag.site.config)
|
61
81
|
end
|
62
82
|
|
83
|
+
# There are a few config settings which can either be booleans,
|
84
|
+
# environment names, or arrays of environment names. This method works it
|
85
|
+
# out and returns a boolean.
|
86
|
+
def env_check(setting)
|
87
|
+
if setting.is_a? Array
|
88
|
+
setting.include? jekyll_env
|
89
|
+
elsif setting.is_a? String
|
90
|
+
setting == jekyll_env
|
91
|
+
elsif [true, false].include? setting
|
92
|
+
setting
|
93
|
+
else
|
94
|
+
raise ArgumentError,
|
95
|
+
"#{setting} must either be a string, an array, or a boolean."
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
63
99
|
def setting_merge(default, jekyll)
|
64
100
|
jekyll.merge default do |_key, config_setting, default_setting|
|
65
101
|
if default_setting.respond_to? :merge
|
@@ -69,8 +69,20 @@ module PictureTag
|
|
69
69
|
element.media = srcset.media_attribute if srcset.media
|
70
70
|
end
|
71
71
|
|
72
|
-
#
|
72
|
+
# GeneratedImage class, not HTML
|
73
73
|
def build_fallback_image
|
74
|
+
fallback = GeneratedImage.new(
|
75
|
+
source_file: PictureTag.source_images.first,
|
76
|
+
format: PictureTag.fallback_format,
|
77
|
+
width: PictureTag.fallback_width
|
78
|
+
)
|
79
|
+
|
80
|
+
return fallback if fallback.exists?
|
81
|
+
|
82
|
+
build_new_fallback_image
|
83
|
+
end
|
84
|
+
|
85
|
+
def build_new_fallback_image
|
74
86
|
GeneratedImage.new(
|
75
87
|
source_file: PictureTag.source_images.first,
|
76
88
|
format: PictureTag.fallback_format,
|
@@ -4,6 +4,7 @@ module PictureTag
|
|
4
4
|
# to be reused by many different generated images.
|
5
5
|
class SourceImage
|
6
6
|
attr_reader :name, :shortname, :missing, :media_preset
|
7
|
+
attr_accessor :digest_guess
|
7
8
|
include MiniMagick
|
8
9
|
|
9
10
|
def initialize(relative_filename, media_preset = nil)
|
@@ -23,12 +24,16 @@ module PictureTag
|
|
23
24
|
def digest
|
24
25
|
@digest ||= if @missing
|
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
|
26
31
|
else
|
27
32
|
Digest::MD5.hexdigest(File.read(@name))[0..5]
|
28
33
|
end
|
29
34
|
end
|
30
35
|
|
31
|
-
# Includes path relative to default
|
36
|
+
# Includes path relative to default source folder and the original filename.
|
32
37
|
def base_name
|
33
38
|
@shortname.delete_suffix File.extname(@shortname)
|
34
39
|
end
|
@@ -24,7 +24,7 @@ module PictureTag
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def files
|
27
|
-
@files ||=
|
27
|
+
@files ||= build_files
|
28
28
|
end
|
29
29
|
|
30
30
|
def to_a
|
@@ -46,15 +46,6 @@ module PictureTag
|
|
46
46
|
nil
|
47
47
|
end
|
48
48
|
|
49
|
-
# Check our source image size vs requested sizes
|
50
|
-
def check_widths(targets)
|
51
|
-
if targets.any? { |t| t > @source_image.width }
|
52
|
-
handle_small_source(targets, @source_image.width)
|
53
|
-
else
|
54
|
-
targets
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
49
|
# Generates an HTML attribute
|
59
50
|
def media_attribute
|
60
51
|
"(#{PictureTag.media_presets[@media]})"
|
@@ -62,17 +53,39 @@ module PictureTag
|
|
62
53
|
|
63
54
|
private
|
64
55
|
|
65
|
-
def
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
56
|
+
def build_files
|
57
|
+
# By 'files', we mean the GeneratedImage class.
|
58
|
+
return target_files if target_files.all?(&:exists?)
|
59
|
+
|
60
|
+
# This triggers GeneratedImage to actually build an image file.
|
61
|
+
files = checked_targets
|
62
|
+
files.each(&:generate)
|
63
|
+
|
64
|
+
files
|
65
|
+
end
|
70
66
|
|
71
|
-
|
67
|
+
def checked_targets
|
68
|
+
if target_files.any? { |f| f.width > @source_image.width }
|
72
69
|
|
73
|
-
|
70
|
+
small_source_warn
|
74
71
|
|
75
|
-
|
72
|
+
files = target_files.reject { |f| f.width >= @source_image.width }
|
73
|
+
files.push(generate_file(@source_image.width))
|
74
|
+
end
|
75
|
+
|
76
|
+
files || target_files
|
77
|
+
end
|
78
|
+
|
79
|
+
def target_files
|
80
|
+
@target_files ||= widths.collect { |w| generate_file(w) }
|
81
|
+
end
|
82
|
+
|
83
|
+
def small_source_warn
|
84
|
+
Utils.warning(
|
85
|
+
" #{@source_image.shortname} is #{@source_image.width}px wide,"\
|
86
|
+
" smaller than at least one size in the set #{widths}. Will not"\
|
87
|
+
' enlarge.'
|
88
|
+
)
|
76
89
|
end
|
77
90
|
|
78
91
|
def generate_file(width)
|
@@ -6,11 +6,9 @@ module PictureTag
|
|
6
6
|
private
|
7
7
|
|
8
8
|
def widths
|
9
|
-
|
9
|
+
PictureTag.preset['pixel_ratios'].collect do |p|
|
10
10
|
p * PictureTag.preset['base_width']
|
11
11
|
end
|
12
|
-
|
13
|
-
check_widths target
|
14
12
|
end
|
15
13
|
|
16
14
|
def build_srcset_entry(file)
|
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.9.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:
|
13
|
+
date: 2020-02-04 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|