jekyll_picture_tag 1.13.0 → 2.0.2
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/.envrc +4 -0
- data/.github/workflows/code-checks.yml +33 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +29 -76
- data/.ruby-version +1 -1
- data/docs/.envrc +2 -0
- data/docs/devs/contributing/code.md +14 -4
- data/docs/devs/contributing/docs.md +24 -6
- data/docs/devs/contributing/setup.md +21 -1
- data/docs/devs/contributing/testing.md +19 -37
- data/docs/devs/releases.md +45 -4
- data/docs/index.md +43 -18
- data/docs/logo.png +0 -0
- data/docs/logo.svg +880 -0
- data/docs/users/configuration/disable.md +1 -1
- data/docs/users/configuration/ignore_missing.md +1 -1
- data/docs/users/configuration/kramdown_fix.md +1 -1
- data/docs/users/configuration/suppress_warnings.md +1 -1
- data/docs/users/configuration/urls.md +69 -0
- data/docs/users/deployment.md +49 -0
- data/docs/users/getting_started.md +55 -0
- data/docs/users/installation.md +18 -38
- data/docs/users/liquid_tag/argument_reference/crop.md +21 -36
- data/docs/users/liquid_tag/examples.md +13 -25
- data/docs/users/liquid_tag/index.md +1 -1
- data/docs/users/notes/{migration.md → migration_1.md} +1 -1
- data/docs/users/notes/migration_2.md +99 -0
- data/docs/users/presets/cropping.md +21 -22
- data/docs/users/presets/default.md +11 -2
- data/docs/users/presets/examples.md +77 -45
- data/docs/users/presets/fallback_image.md +1 -1
- data/docs/users/presets/html_attributes.md +1 -1
- data/docs/users/presets/image_formats.md +3 -3
- data/docs/users/presets/image_quality.md +71 -56
- data/docs/users/presets/index.md +19 -45
- data/docs/users/presets/link_source.md +1 -1
- data/docs/users/presets/media_queries.md +1 -1
- data/docs/users/presets/nomarkdown_override.md +1 -1
- data/docs/users/presets/pixel_ratio_srcsets.md +1 -1
- data/docs/users/presets/width_height_attributes.md +1 -1
- data/docs/users/presets/width_srcsets.md +61 -23
- data/docs/users/presets/writing_presets.md +65 -0
- data/docs/users/tutorial.md +97 -0
- data/jekyll_picture_tag.gemspec +38 -23
- data/lib/jekyll_picture_tag.rb +8 -5
- data/lib/jekyll_picture_tag/cache.rb +64 -3
- data/lib/jekyll_picture_tag/defaults/global.rb +18 -0
- data/lib/jekyll_picture_tag/defaults/presets.rb +57 -0
- data/lib/jekyll_picture_tag/images.rb +1 -0
- data/lib/jekyll_picture_tag/images/generated_image.rb +25 -60
- data/lib/jekyll_picture_tag/images/image_file.rb +105 -0
- data/lib/jekyll_picture_tag/images/img_uri.rb +3 -10
- data/lib/jekyll_picture_tag/images/source_image.rb +44 -9
- data/lib/jekyll_picture_tag/instructions.rb +70 -6
- data/lib/jekyll_picture_tag/instructions/children/config.rb +128 -0
- data/lib/jekyll_picture_tag/instructions/children/context.rb +24 -0
- data/lib/jekyll_picture_tag/instructions/children/params.rb +90 -0
- data/lib/jekyll_picture_tag/instructions/children/parsers.rb +48 -0
- data/lib/jekyll_picture_tag/instructions/children/preset.rb +182 -0
- data/lib/jekyll_picture_tag/instructions/parents/conditional_instruction.rb +69 -0
- data/lib/jekyll_picture_tag/instructions/parents/env_instruction.rb +29 -0
- data/lib/jekyll_picture_tag/output_formats/basic.rb +5 -17
- data/lib/jekyll_picture_tag/parsers.rb +6 -0
- data/lib/jekyll_picture_tag/{instructions → parsers}/arg_splitter.rb +1 -1
- data/lib/jekyll_picture_tag/parsers/configuration.rb +28 -0
- data/lib/jekyll_picture_tag/{instructions → parsers}/html_attributes.rb +1 -1
- data/lib/jekyll_picture_tag/parsers/image_backend.rb +33 -0
- data/lib/jekyll_picture_tag/parsers/preset.rb +43 -0
- data/lib/jekyll_picture_tag/{instructions → parsers}/tag_parser.rb +15 -12
- data/lib/jekyll_picture_tag/router.rb +35 -93
- data/lib/jekyll_picture_tag/srcsets/basic.rb +4 -10
- data/lib/jekyll_picture_tag/utils.rb +10 -20
- data/lib/jekyll_picture_tag/version.rb +1 -1
- data/readme.md +48 -9
- metadata +161 -80
- data/.travis.yml +0 -8
- data/Dockerfile +0 -9
- data/docs/users/configuration/cdn.md +0 -35
- data/docs/users/configuration/relative_urls.md +0 -15
- data/docs/users/notes/input_checking.md +0 -6
- data/jekyll-picture-tag.gemspec +0 -52
- data/lib/jekyll-picture-tag.rb +0 -25
- data/lib/jekyll_picture_tag/cache/base.rb +0 -59
- data/lib/jekyll_picture_tag/cache/generated.rb +0 -20
- data/lib/jekyll_picture_tag/cache/source.rb +0 -19
- data/lib/jekyll_picture_tag/defaults/global.yml +0 -11
- data/lib/jekyll_picture_tag/defaults/presets.yml +0 -11
- data/lib/jekyll_picture_tag/instructions/configuration.rb +0 -121
- data/lib/jekyll_picture_tag/instructions/preset.rb +0 -122
- data/lib/jekyll_picture_tag/instructions/set.rb +0 -75
@@ -0,0 +1,182 @@
|
|
1
|
+
require 'mime-types'
|
2
|
+
|
3
|
+
module PictureTag
|
4
|
+
module Instructions
|
5
|
+
# Returns an instance of the correct markup format's corresponding class
|
6
|
+
class OutputClass < Instruction
|
7
|
+
private
|
8
|
+
|
9
|
+
def source
|
10
|
+
PictureTag.preset['markup']
|
11
|
+
end
|
12
|
+
|
13
|
+
def coerce
|
14
|
+
Object.const_get(class_name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def class_name
|
18
|
+
'PictureTag::OutputFormats::' + Utils.titleize(source)
|
19
|
+
end
|
20
|
+
|
21
|
+
def valid?
|
22
|
+
source.is_a?(String) &&
|
23
|
+
!source.include?(' ') &&
|
24
|
+
Object.const_defined?(class_name)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Image formats
|
29
|
+
class Formats < Instruction
|
30
|
+
private
|
31
|
+
|
32
|
+
def source
|
33
|
+
PictureTag.preset['formats']
|
34
|
+
end
|
35
|
+
|
36
|
+
def coerce
|
37
|
+
[source].flatten
|
38
|
+
end
|
39
|
+
|
40
|
+
def valid?
|
41
|
+
coerced.all? do |format|
|
42
|
+
types = MIME::Types.type_for(format)
|
43
|
+
format == 'original' ||
|
44
|
+
types.length == 1 && types.first.media_type == 'image'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Fallback image format
|
50
|
+
class FallbackFormat < Instruction
|
51
|
+
private
|
52
|
+
|
53
|
+
def source
|
54
|
+
PictureTag.preset['fallback_format']
|
55
|
+
end
|
56
|
+
|
57
|
+
def valid?
|
58
|
+
types = MIME::Types.type_for(coerced)
|
59
|
+
coerced == 'original' ||
|
60
|
+
types.length == 1 && types.first.media_type == 'image'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Fallback Image width
|
65
|
+
class FallbackWidth < Instruction
|
66
|
+
private
|
67
|
+
|
68
|
+
def source
|
69
|
+
PictureTag.preset['fallback_width']
|
70
|
+
end
|
71
|
+
|
72
|
+
def valid?
|
73
|
+
source.is_a? Integer
|
74
|
+
end
|
75
|
+
|
76
|
+
def error_message
|
77
|
+
<<~HEREDOC
|
78
|
+
fallback_width for preset '#{PictureTag.preset.name}' is invalid. It
|
79
|
+
should be a positive integer. You can use underscores as separators:
|
80
|
+
1200
|
81
|
+
1_200
|
82
|
+
HEREDOC
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Whether to add a {::nomarkdown} wrapper
|
87
|
+
class Nomarkdown < Instruction
|
88
|
+
private
|
89
|
+
|
90
|
+
def source
|
91
|
+
{
|
92
|
+
config: PictureTag.pconfig['nomarkdown'],
|
93
|
+
md_page: Utils.markdown_page?,
|
94
|
+
preset: PictureTag.preset['nomarkdown']
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
def valid?
|
99
|
+
source.fetch_values(:preset, :config).all? do |setting|
|
100
|
+
[true, false, nil].include? setting
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def coerce
|
105
|
+
return source[:preset] unless source[:preset].nil?
|
106
|
+
|
107
|
+
source[:md_page] && source[:config]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Returns widths for a given media query.
|
112
|
+
class Widths < ConditionalInstruction
|
113
|
+
private
|
114
|
+
|
115
|
+
def setting_name
|
116
|
+
'widths'
|
117
|
+
end
|
118
|
+
|
119
|
+
def setting_prefix
|
120
|
+
'media'
|
121
|
+
end
|
122
|
+
|
123
|
+
def acceptable_types
|
124
|
+
super + [Array]
|
125
|
+
end
|
126
|
+
|
127
|
+
def valid_hash?
|
128
|
+
hash = source[:hash]
|
129
|
+
return true if hash.nil?
|
130
|
+
|
131
|
+
hash.is_a?(Hash) && valid_hash_keys?(hash) && valid_hash_values?(hash)
|
132
|
+
end
|
133
|
+
|
134
|
+
def valid_hash_keys?(hash)
|
135
|
+
hash.keys.all? { |k| k.is_a? String }
|
136
|
+
end
|
137
|
+
|
138
|
+
def valid_hash_values?(hash)
|
139
|
+
hash.values.all? do |val|
|
140
|
+
val.is_a?(Array) && val.all? { |subval| subval.is_a? Integer }
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Returns quality for a given width.
|
146
|
+
class Quality < ConditionalInstruction
|
147
|
+
private
|
148
|
+
|
149
|
+
def setting_name
|
150
|
+
'quality'
|
151
|
+
end
|
152
|
+
|
153
|
+
def setting_prefix
|
154
|
+
'format'
|
155
|
+
end
|
156
|
+
|
157
|
+
def acceptable_types
|
158
|
+
super + [Integer, Hash]
|
159
|
+
end
|
160
|
+
|
161
|
+
def coerce(format = nil, width = nil)
|
162
|
+
setting = super(format)
|
163
|
+
|
164
|
+
return setting unless setting.is_a? Hash
|
165
|
+
|
166
|
+
parse_quality_hash(setting, width)
|
167
|
+
end
|
168
|
+
|
169
|
+
# Works out linearly interpolated quality settings.
|
170
|
+
def parse_quality_hash(points, width)
|
171
|
+
# The points can be given in any order.
|
172
|
+
low, high = *points.keys.map(&:to_i).sort
|
173
|
+
|
174
|
+
case width
|
175
|
+
when 0..low then points[low]
|
176
|
+
when low..high then Utils.interpolate(points.keys, points.values, width)
|
177
|
+
when high..999_999 then points[high]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module PictureTag
|
2
|
+
module Instructions
|
3
|
+
# Many inputs take a common format: a generic setting which applies all of
|
4
|
+
# the time, or more specific versions of that setting for specific
|
5
|
+
# circumstances. For example, quality can be set globally, or per image
|
6
|
+
# format. This instruction class handles those cases.
|
7
|
+
#
|
8
|
+
# To use, you must at minimum define setting_basename, setting_prefix, and
|
9
|
+
# add to the acceptable_types (or write your own validation).
|
10
|
+
class ConditionalInstruction < Instruction
|
11
|
+
def value(*args)
|
12
|
+
coerce(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def setting_basename
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
|
21
|
+
# Special condition for setting; media, crop, etc
|
22
|
+
def setting_prefix
|
23
|
+
raise NotImplementedError
|
24
|
+
end
|
25
|
+
|
26
|
+
def acceptable_types
|
27
|
+
[NilClass]
|
28
|
+
end
|
29
|
+
|
30
|
+
def coerce(arg)
|
31
|
+
raise ArgumentError unless valid?
|
32
|
+
|
33
|
+
value_hash[arg]
|
34
|
+
end
|
35
|
+
|
36
|
+
def source
|
37
|
+
{
|
38
|
+
hash: PictureTag.preset[setting_prefix + '_' + setting_name],
|
39
|
+
default: PictureTag.preset[setting_name]
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def value_hash
|
44
|
+
vals = source[:hash] || {}
|
45
|
+
vals.default = source[:default]
|
46
|
+
|
47
|
+
vals
|
48
|
+
end
|
49
|
+
|
50
|
+
def valid?
|
51
|
+
valid_hash? && valid_default?
|
52
|
+
end
|
53
|
+
|
54
|
+
def acceptable_type?(value)
|
55
|
+
acceptable_types.any? { |type| value.is_a? type }
|
56
|
+
end
|
57
|
+
|
58
|
+
def valid_hash?
|
59
|
+
source[:hash].nil? || source[:hash].values.all? do |v|
|
60
|
+
acceptable_type?(v)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def valid_default?
|
65
|
+
acceptable_type? source[:default]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module PictureTag
|
2
|
+
module Instructions
|
3
|
+
# There are a few config settings which are environment dependent, and can
|
4
|
+
# either be booleans, environment names, or arrays of environment names.
|
5
|
+
# This class works it out and returns a boolean.
|
6
|
+
class EnvInstruction < Instruction
|
7
|
+
private
|
8
|
+
|
9
|
+
def coerce
|
10
|
+
get_bool(source)
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_bool(value)
|
14
|
+
case value
|
15
|
+
when true, false, nil then value
|
16
|
+
when String then value == PictureTag.jekyll_env
|
17
|
+
when Array then value.include? PictureTag.jekyll_env
|
18
|
+
when Hash then get_bool(value[:setting])
|
19
|
+
else raise ArgumentError, error_message
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def error_message
|
24
|
+
"JPT - #{setting_name} must be a boolean, an environment name," \
|
25
|
+
' or an array of environment names.'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -76,9 +76,7 @@ module PictureTag
|
|
76
76
|
image = GeneratedImage.new(
|
77
77
|
source_file: PictureTag.source_images.first,
|
78
78
|
format: PictureTag.fallback_format,
|
79
|
-
width: checked_fallback_width
|
80
|
-
crop: PictureTag.crop,
|
81
|
-
gravity: PictureTag.gravity
|
79
|
+
width: checked_fallback_width
|
82
80
|
)
|
83
81
|
|
84
82
|
image.generate
|
@@ -92,9 +90,7 @@ module PictureTag
|
|
92
90
|
@fallback_candidate ||= GeneratedImage.new(
|
93
91
|
source_file: PictureTag.source_images.first,
|
94
92
|
format: PictureTag.fallback_format,
|
95
|
-
width: PictureTag.fallback_width
|
96
|
-
crop: PictureTag.crop,
|
97
|
-
gravity: PictureTag.gravity
|
93
|
+
width: PictureTag.fallback_width
|
98
94
|
)
|
99
95
|
end
|
100
96
|
|
@@ -119,22 +115,14 @@ module PictureTag
|
|
119
115
|
PictureTag.source_images.first
|
120
116
|
end
|
121
117
|
|
122
|
-
def source_width
|
123
|
-
if PictureTag.crop
|
124
|
-
fallback_candidate.source_width
|
125
|
-
else
|
126
|
-
source.width
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
118
|
def checked_fallback_width
|
131
119
|
target = PictureTag.fallback_width
|
132
120
|
|
133
|
-
if target >
|
121
|
+
if target > source.width
|
134
122
|
Utils.warning "#{source.shortname} is smaller than the " \
|
135
|
-
"requested fallback width of #{target}px. Using #{
|
123
|
+
"requested fallback width of #{target}px. Using #{source.width}" \
|
136
124
|
' px instead.'
|
137
|
-
|
125
|
+
source.width
|
138
126
|
else
|
139
127
|
target
|
140
128
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module PictureTag
|
2
|
+
module Parsers
|
3
|
+
# Global config (big picture). loads jekyll data/config files, and the j-p-t
|
4
|
+
# defaults from included yml files.
|
5
|
+
class Configuration
|
6
|
+
# returns jekyll's configuration (picture is a subset)
|
7
|
+
def [](key)
|
8
|
+
content[key]
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def content
|
14
|
+
@content ||= setting_merge(DEFAULT_CONFIG, PictureTag.site.config)
|
15
|
+
end
|
16
|
+
|
17
|
+
def setting_merge(default, jekyll)
|
18
|
+
jekyll.merge default do |_key, config_setting, default_setting|
|
19
|
+
if default_setting.respond_to? :merge
|
20
|
+
setting_merge(default_setting, config_setting)
|
21
|
+
else
|
22
|
+
config_setting
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module PictureTag
|
2
|
+
module Parsers
|
3
|
+
# Returns information regarding image handlers
|
4
|
+
class ImageBackend
|
5
|
+
def handler_for(format)
|
6
|
+
if vips_formats.include? format
|
7
|
+
:vips
|
8
|
+
elsif magick_formats.include? format
|
9
|
+
:magick
|
10
|
+
else
|
11
|
+
raise "No support for generating #{format} files in this environment."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns array of formats that vips can save to
|
16
|
+
def vips_formats
|
17
|
+
@vips_formats ||= `vips -l filesave`
|
18
|
+
.scan(/\.[a-z]{1,5}/)
|
19
|
+
.uniq
|
20
|
+
.map { |format| format.strip.delete_prefix('.') }
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns an array of formats that imagemagick can handle.
|
24
|
+
def magick_formats
|
25
|
+
@magick_formats ||= `convert -version`
|
26
|
+
.split("\n")
|
27
|
+
.last
|
28
|
+
.delete_prefix('Delegates (built-in):')
|
29
|
+
.split
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module PictureTag
|
2
|
+
module Parsers
|
3
|
+
# Handles the specific tag image set to construct.
|
4
|
+
class Preset
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
def initialize(name)
|
8
|
+
@name = name
|
9
|
+
end
|
10
|
+
|
11
|
+
def [](key)
|
12
|
+
content[key]
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def content
|
18
|
+
@content ||= DEFAULT_PRESET.merge settings
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def settings
|
24
|
+
PictureTag.site.data.dig('picture', 'presets', name) ||
|
25
|
+
STOCK_PRESETS[name] ||
|
26
|
+
no_preset
|
27
|
+
end
|
28
|
+
|
29
|
+
def no_preset
|
30
|
+
unless name == 'default'
|
31
|
+
Utils.warning(
|
32
|
+
<<~HEREDOC
|
33
|
+
Preset "#{name}" not found in #{PictureTag.config['data_dir']}/picture.yml
|
34
|
+
under 'presets' key, or in stock presets. Using default values."
|
35
|
+
HEREDOC
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
{}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|