jekyll_picture_tag 1.14.0 → 2.0.0pre1
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 +2 -0
- data/.github/workflows/code-checks.yml +2 -12
- data/.rubocop.yml +2 -0
- data/.ruby-version +1 -1
- data/docs/devs/contributing/code.md +11 -3
- data/docs/devs/contributing/testing.md +0 -11
- data/docs/devs/releases.md +20 -0
- data/docs/index.md +32 -17
- data/docs/logo.png +0 -0
- data/docs/logo.svg +880 -0
- data/docs/users/getting_started.md +55 -0
- data/docs/users/installation.md +17 -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 -3
- 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 +70 -55
- data/docs/users/presets/index.md +78 -42
- 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/tutorial.md +97 -0
- data/jekyll_picture_tag.gemspec +33 -23
- data/lib/jekyll_picture_tag.rb +8 -6
- 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 -63
- data/lib/jekyll_picture_tag/images/image_file.rb +90 -0
- data/lib/jekyll_picture_tag/images/img_uri.rb +3 -12
- 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 +41 -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 +5 -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/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 +2 -0
- metadata +124 -106
- data/Dockerfile +0 -9
- data/docs/users/notes/input_checking.md +0 -6
- data/docs/users/presets/strip_metadata.md +0 -13
- data/install_imagemagick.sh +0 -23
- data/jekyll-picture-tag.gemspec +0 -52
- data/lib/jekyll-picture-tag.rb +0 -25
- data/lib/jekyll_picture_tag/cache/base.rb +0 -61
- 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 -13
- data/lib/jekyll_picture_tag/defaults/presets.yml +0 -12
- 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,128 @@
|
|
1
|
+
module PictureTag
|
2
|
+
module Instructions
|
3
|
+
# PictureTag configuration in _config.yml
|
4
|
+
class Pconfig < Instruction
|
5
|
+
def source
|
6
|
+
PictureTag.config['picture']
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# https://example.com/my-base-path/assets/generated-images/image.jpg
|
11
|
+
# ^^^^^^^^^^^^^
|
12
|
+
# | domain | baseurl | directory | filename
|
13
|
+
class Baseurl < Instruction
|
14
|
+
def source
|
15
|
+
{
|
16
|
+
ignore: PictureTag.pconfig['ignore_baseurl'],
|
17
|
+
key: PictureTag.pconfig['baseurl_key']
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def coerce
|
22
|
+
return '' if source[:ignore]
|
23
|
+
|
24
|
+
PictureTag.config[source[:key]] || ''
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Whether to use relative or absolute URLs for images.
|
29
|
+
class RelativeUrl < EnvInstruction
|
30
|
+
def source
|
31
|
+
PictureTag.pconfig['relative_url']
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Image source directory
|
36
|
+
class SourceDir < Instruction
|
37
|
+
private
|
38
|
+
|
39
|
+
def source
|
40
|
+
[
|
41
|
+
PictureTag.site.source,
|
42
|
+
PictureTag.pconfig['source']
|
43
|
+
]
|
44
|
+
end
|
45
|
+
|
46
|
+
def coerce
|
47
|
+
File.join(*source.map(&:to_s))
|
48
|
+
end
|
49
|
+
|
50
|
+
def setting_name
|
51
|
+
'source directory'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Image output directory
|
56
|
+
class DestDir < Instruction
|
57
|
+
private
|
58
|
+
|
59
|
+
def source
|
60
|
+
[
|
61
|
+
PictureTag.site.config['destination'],
|
62
|
+
PictureTag.pconfig['output']
|
63
|
+
]
|
64
|
+
end
|
65
|
+
|
66
|
+
def coerce
|
67
|
+
File.join(*source.map(&:to_s))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Whether to continue if a source image is missing
|
72
|
+
class ContinueOnMissing < EnvInstruction
|
73
|
+
def source
|
74
|
+
PictureTag.pconfig['ignore_missing_images']
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Whether to use a CDN
|
79
|
+
class Cdn < EnvInstruction
|
80
|
+
def source
|
81
|
+
{
|
82
|
+
url: PictureTag.pconfig['cdn_url'],
|
83
|
+
setting: PictureTag.pconfig['cdn_environments']
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
def coerce
|
88
|
+
source[:url] && super
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# CDN URL
|
93
|
+
class CdnUrl < Instruction
|
94
|
+
def source
|
95
|
+
PictureTag.pconfig['cdn_url']
|
96
|
+
end
|
97
|
+
|
98
|
+
def valid?
|
99
|
+
require 'uri'
|
100
|
+
uri = URI(source)
|
101
|
+
|
102
|
+
# If the URI library can't parse it, it's not valid.
|
103
|
+
uri.scheme && uri.host
|
104
|
+
end
|
105
|
+
|
106
|
+
def error_message
|
107
|
+
<<~HEREDOC
|
108
|
+
cdn_url must be a valid URI in the following format: https://example.com/
|
109
|
+
current setting: #{source}
|
110
|
+
HEREDOC
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Disable JPT?
|
115
|
+
class Disabled < EnvInstruction
|
116
|
+
def source
|
117
|
+
PictureTag.pconfig['disabled']
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Fast build?
|
122
|
+
class FastBuild < EnvInstruction
|
123
|
+
def source
|
124
|
+
PictureTag.pconfig['fast_build']
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module PictureTag
|
2
|
+
module Instructions
|
3
|
+
# Jekyll site info
|
4
|
+
class Site < Instruction
|
5
|
+
def source
|
6
|
+
PictureTag.context.registers[:site]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# Current page in jekyll site
|
11
|
+
class Page < Instruction
|
12
|
+
def source
|
13
|
+
PictureTag.context.registers[:page]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Digs into jekyll context, returns current environment
|
18
|
+
class JekyllEnv < Instruction
|
19
|
+
def source
|
20
|
+
PictureTag.context.environments.first['jekyll']['environment']
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module PictureTag
|
2
|
+
module Instructions
|
3
|
+
# Builds instances of all source images.
|
4
|
+
class SourceImages < Instruction
|
5
|
+
def source
|
6
|
+
{
|
7
|
+
source_names: PictureTag.params.source_names,
|
8
|
+
media_presets: PictureTag.params.media_presets
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
def coerce
|
13
|
+
sources = [PictureTag::SourceImage.new(source[:source_names].shift)]
|
14
|
+
|
15
|
+
while source[:source_names].any?
|
16
|
+
sources << PictureTag::SourceImage.new(
|
17
|
+
source[:source_names].shift, source[:media_presets].shift
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
sources
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Which crop to use for a given media query. Can be given either in params
|
26
|
+
# or preset.
|
27
|
+
class Crop < ConditionalInstruction
|
28
|
+
def source
|
29
|
+
super.merge(
|
30
|
+
{ params: PictureTag.params.crop }
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
def coerce(media = nil)
|
35
|
+
raise ArgumentError unless valid?
|
36
|
+
|
37
|
+
source[:params][media] || value_hash[media]
|
38
|
+
end
|
39
|
+
|
40
|
+
def setting_basename
|
41
|
+
'crop'
|
42
|
+
end
|
43
|
+
|
44
|
+
def setting_prefix
|
45
|
+
'media'
|
46
|
+
end
|
47
|
+
|
48
|
+
def acceptable_types
|
49
|
+
super + [String]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Which vips interestingness setting to use for a given media query. Can be
|
54
|
+
# given either in params or preset.
|
55
|
+
class Keep < ConditionalInstruction
|
56
|
+
def source
|
57
|
+
super.merge(
|
58
|
+
{ params: PictureTag.params.keep }
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
def coerce(media = nil)
|
63
|
+
raise ArgumentError unless valid?
|
64
|
+
|
65
|
+
lookup[source[:params][media] || super(media)]
|
66
|
+
end
|
67
|
+
|
68
|
+
def lookup
|
69
|
+
{
|
70
|
+
'center' => :centre,
|
71
|
+
'centre' => :centre,
|
72
|
+
'attention' => :attention,
|
73
|
+
'entropy' => :entropy
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def setting_basename
|
78
|
+
'keep'
|
79
|
+
end
|
80
|
+
|
81
|
+
def setting_prefix
|
82
|
+
'media'
|
83
|
+
end
|
84
|
+
|
85
|
+
def acceptable_types
|
86
|
+
super + [String]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module PictureTag
|
2
|
+
module Instructions
|
3
|
+
# PictureTag configuration
|
4
|
+
class Config < Instruction
|
5
|
+
def source
|
6
|
+
PictureTag::Parsers::Configuration.new
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# Tag parameters
|
11
|
+
class Params < Instruction
|
12
|
+
def source
|
13
|
+
PictureTag::Parsers::TagParser.new PictureTag.raw_params
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Currently selected preset
|
18
|
+
class Preset < Instruction
|
19
|
+
def source
|
20
|
+
PictureTag::Parsers::Preset.new PictureTag.params.preset_name
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Handles non-image arguments to liquid tag and preset.
|
25
|
+
class HtmlAttributes < Instruction
|
26
|
+
def source
|
27
|
+
PictureTag::Parsers::HTMLAttributeSet.new PictureTag.params.leftovers
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# TODO: rename to MediaQueries
|
32
|
+
# Returns user-defined media queries.
|
33
|
+
class MediaPresets < Instruction
|
34
|
+
def source
|
35
|
+
STOCK_MEDIA_QUERIES.merge(
|
36
|
+
PictureTag.site.data.dig('picture', 'media_queries') || {}
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -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
|