jekyll_picture_tag 1.14.0 → 2.0.3
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 +38 -2
- data/docs/index.md +43 -18
- data/docs/logo.png +0 -0
- data/docs/logo.svg +880 -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 +10 -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 +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 +105 -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 +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 +46 -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 +38 -0
- metadata +126 -105
- 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
@@ -1,6 +1,70 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
module PictureTag
|
2
|
+
# Instructions obtain, validate, and typecast/coerce input values. These
|
3
|
+
# inputs are either taken directly from jekyll's inputs, or handled by parsers
|
4
|
+
# first.
|
5
|
+
#
|
6
|
+
# Logic which affects only a single setting belongs in Instructions, while
|
7
|
+
# logic which affects multiple settings belongs in Parsers.
|
8
|
+
#
|
9
|
+
# Since instruction classes are so small, we define several per file in the
|
10
|
+
# instructions directory to save on boilerplate. All fall under the
|
11
|
+
# Instructions module namespace.
|
12
|
+
module Instructions
|
13
|
+
# Generic instruction, meant to be inherited. Children of this class must
|
14
|
+
# override the source method, and likely want to override valid?, coerce,
|
15
|
+
# and error_message as applicable.
|
16
|
+
class Instruction
|
17
|
+
# Memoized value of the given instruction. This is the public API.
|
18
|
+
def value
|
19
|
+
return @value if defined?(@value)
|
20
|
+
|
21
|
+
raise ArgumentError, error_message unless valid?
|
22
|
+
|
23
|
+
@value = coerced
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Source(s) of truth - where does this setting come from? Logic does not
|
29
|
+
# belong here. If information comes from muliple places, return an array
|
30
|
+
# or a hash.
|
31
|
+
def source
|
32
|
+
raise NotImplementedError
|
33
|
+
end
|
34
|
+
|
35
|
+
# Determine whether or not the input(s) are valid.
|
36
|
+
def valid?
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
# Convert input(s) to output.
|
41
|
+
def coerce
|
42
|
+
source
|
43
|
+
end
|
44
|
+
|
45
|
+
# Message returned if validation fails. Override this with something more
|
46
|
+
# helpful.
|
47
|
+
def error_message
|
48
|
+
"JPT - #{setting_name} received an invalid argument: #{source}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def coerced
|
52
|
+
return @coerced if defined?(@coerced)
|
53
|
+
|
54
|
+
@coerced = coerce
|
55
|
+
end
|
56
|
+
|
57
|
+
def setting_name
|
58
|
+
Utils.snakeize(self.class.to_s.split('::').last)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Load Parents
|
65
|
+
Dir[File.dirname(__FILE__) + '/instructions/parents/*.rb']
|
66
|
+
.sort.each { |file| require file }
|
67
|
+
|
68
|
+
# Load children:
|
69
|
+
Dir[File.dirname(__FILE__) + '/instructions/children/*.rb']
|
70
|
+
.sort.each { |file| require file }
|
@@ -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,48 @@
|
|
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
|
+
|
41
|
+
# Main job is to determine which backend should handle which image formats.
|
42
|
+
class Backend < Instruction
|
43
|
+
def source
|
44
|
+
PictureTag::Parsers::ImageBackend.new
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
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
|