inkcite 1.14.0 → 1.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/assets/init/config.yml +2 -0
- data/assets/social/facebook.png +0 -0
- data/assets/social/instagram.png +0 -0
- data/assets/social/pintrest.png +0 -0
- data/assets/social/twitter.png +0 -0
- data/inkcite.gemspec +2 -2
- data/lib/inkcite.rb +1 -0
- data/lib/inkcite/cli/base.rb +32 -6
- data/lib/inkcite/cli/preview.rb +24 -28
- data/lib/inkcite/cli/server.rb +22 -19
- data/lib/inkcite/cli/test.rb +1 -1
- data/lib/inkcite/email.rb +8 -4
- data/lib/inkcite/facade/animation.rb +4 -0
- data/lib/inkcite/facade/keyframe.rb +26 -3
- data/lib/inkcite/image/base.rb +38 -0
- data/lib/inkcite/image/guetzli_minifier.rb +62 -0
- data/lib/inkcite/image/image_minifier.rb +143 -0
- data/lib/inkcite/image/image_optim_minifier.rb +90 -0
- data/lib/inkcite/image/mozjpeg_minifier.rb +92 -0
- data/lib/inkcite/mailer.rb +201 -112
- data/lib/inkcite/minifier.rb +2 -146
- data/lib/inkcite/post_processor.rb +13 -0
- data/lib/inkcite/renderer.rb +19 -0
- data/lib/inkcite/renderer/background.rb +53 -14
- data/lib/inkcite/renderer/base.rb +29 -15
- data/lib/inkcite/renderer/button.rb +1 -1
- data/lib/inkcite/renderer/carousel.rb +245 -0
- data/lib/inkcite/renderer/container_base.rb +10 -0
- data/lib/inkcite/renderer/div.rb +1 -3
- data/lib/inkcite/renderer/fireworks.rb +54 -40
- data/lib/inkcite/renderer/footnote.rb +22 -2
- data/lib/inkcite/renderer/image.rb +11 -0
- data/lib/inkcite/renderer/image_base.rb +3 -6
- data/lib/inkcite/renderer/in_browser.rb +4 -0
- data/lib/inkcite/renderer/link.rb +39 -12
- data/lib/inkcite/renderer/mobile_image.rb +1 -1
- data/lib/inkcite/renderer/responsive.rb +9 -1
- data/lib/inkcite/renderer/social.rb +31 -3
- data/lib/inkcite/renderer/special_effect.rb +22 -13
- data/lib/inkcite/renderer/sup.rb +32 -0
- data/lib/inkcite/renderer/table_base.rb +3 -0
- data/lib/inkcite/renderer/topic.rb +76 -0
- data/lib/inkcite/renderer/trademark.rb +47 -0
- data/lib/inkcite/renderer/video_preview.rb +3 -2
- data/lib/inkcite/uploader.rb +2 -3
- data/lib/inkcite/util.rb +51 -0
- data/lib/inkcite/version.rb +1 -1
- data/lib/inkcite/view.rb +140 -54
- data/lib/inkcite/view/context.rb +1 -31
- data/lib/inkcite/view/media_query.rb +6 -0
- data/test/animation_spec.rb +7 -0
- data/test/parser_spec.rb +1 -1
- data/test/renderer/background_spec.rb +16 -12
- data/test/renderer/div_spec.rb +11 -0
- data/test/renderer/footnote_spec.rb +5 -1
- data/test/renderer/image_spec.rb +51 -28
- data/test/renderer/link_spec.rb +20 -8
- data/test/renderer/lorem_spec.rb +2 -2
- data/test/renderer/mobile_image_spec.rb +6 -0
- data/test/renderer/mobile_style_spec.rb +3 -3
- data/test/renderer/redacted_spec.rb +2 -2
- data/test/renderer/social_spec.rb +6 -6
- data/test/renderer/table_spec.rb +4 -0
- data/test/renderer/topic_spec.rb +28 -0
- data/test/renderer/trademark_spec.rb +40 -0
- data/test/renderer/video_preview_spec.rb +1 -1
- data/test/test_helper.rb +14 -0
- data/test/view_spec.rb +4 -0
- metadata +26 -12
- data/assets/init/image_optim.yml +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f77f5972f324c7fd1d94e0e62ad167331636c78
|
4
|
+
data.tar.gz: 86ce04170afb3b33b76aae7b484eac7247de870d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78f601288da10bd3db71580b7439c70582a0ec1b9bed2458b9bb79e1e4f6266c8c60cb2c55756fb36809e0ffb003791c150b0a9a010fd375bd4ac9bebd1a5d19
|
7
|
+
data.tar.gz: 7e817e4e9e5d38df8950ecc8d390bbfe9f3540703b95149e700b90327ce002fcbbe1a492b94baccff4c9faed55a1efe2b8f8ad5e95f044d8d299f1c0cb880fef
|
data/assets/init/config.yml
CHANGED
@@ -17,6 +17,8 @@ minify: true
|
|
17
17
|
# https://inkcite.readme.io/v1.0/docs/image-optimization
|
18
18
|
optimize-images: true
|
19
19
|
|
20
|
+
jpg-quality: 90
|
21
|
+
|
20
22
|
# When empty links are found in content, this is the URL that will be
|
21
23
|
# included instead - so that clients understand this link is missing
|
22
24
|
# and needs to be provided.
|
data/assets/social/facebook.png
CHANGED
Binary file
|
Binary file
|
data/assets/social/pintrest.png
CHANGED
Binary file
|
data/assets/social/twitter.png
CHANGED
Binary file
|
data/inkcite.gemspec
CHANGED
@@ -27,17 +27,17 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.add_dependency 'builder'
|
28
28
|
spec.add_dependency 'chunky_png'
|
29
29
|
spec.add_dependency 'erubis'
|
30
|
-
spec.add_dependency 'faker'
|
30
|
+
spec.add_dependency 'faker', '1.7.2'
|
31
31
|
spec.add_dependency 'guard'
|
32
32
|
spec.add_dependency 'guard-livereload'
|
33
33
|
spec.add_dependency 'htmlbeautifier'
|
34
34
|
spec.add_dependency 'image_optim'
|
35
35
|
spec.add_dependency 'image_optim_pack'
|
36
|
-
spec.add_dependency 'kraken-io'
|
37
36
|
spec.add_dependency 'listen'
|
38
37
|
spec.add_dependency 'litmus'
|
39
38
|
spec.add_dependency 'mail'
|
40
39
|
spec.add_dependency 'mailgun-ruby'
|
40
|
+
spec.add_dependency 'mozjpeg'
|
41
41
|
spec.add_dependency 'net-sftp'
|
42
42
|
spec.add_dependency 'rack'
|
43
43
|
spec.add_dependency 'rack-livereload'
|
data/lib/inkcite.rb
CHANGED
data/lib/inkcite/cli/base.rb
CHANGED
@@ -41,20 +41,46 @@ module Inkcite
|
|
41
41
|
Cli::Init.invoke(name, options)
|
42
42
|
end
|
43
43
|
|
44
|
+
desc 'minify', 'Minify the images in the project'
|
45
|
+
option :force,
|
46
|
+
:aliases => '-f',
|
47
|
+
:desc => 'Force re-optimize every image, not just the updated ones',
|
48
|
+
:type => :boolean
|
49
|
+
option :image,
|
50
|
+
:aliases => '-i',
|
51
|
+
:desc => 'Optimize a specific image',
|
52
|
+
:type => :string
|
53
|
+
def minify
|
54
|
+
|
55
|
+
if options[:image]
|
56
|
+
Image::ImageMinifier.minify(email, options[:image], true)
|
57
|
+
|
58
|
+
else
|
59
|
+
Image::ImageMinifier.minify_all(email, options[:force])
|
60
|
+
|
61
|
+
original_size = Util.dir_size(email.image_dir)
|
62
|
+
compressed_size = Util.dir_size(email.optimized_image_dir)
|
63
|
+
compressed_percent = Image::ImageMinifier.compressed_percent(original_size, compressed_size)
|
64
|
+
|
65
|
+
puts "Compressed from #{Util.pretty_file_size(original_size)} to #{Util.pretty_file_size(compressed_size)} (#{compressed_percent}%)"
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
44
70
|
desc 'preview TO [options]', 'Send a preview of the email to a recipient list: developer, internal or client'
|
45
71
|
option :version,
|
46
72
|
:aliases => '-v',
|
47
73
|
:desc => 'Preview a specific version of the email'
|
48
|
-
option :
|
49
|
-
:aliases => '-
|
50
|
-
:desc => '
|
51
|
-
:type => :
|
74
|
+
option :count,
|
75
|
+
:aliases => '-c',
|
76
|
+
:desc => 'Override the automatic preview numbering',
|
77
|
+
:type => :numeric
|
52
78
|
option :'no-upload',
|
53
79
|
:desc => 'Skip the asset upload, email the preview immediately',
|
54
80
|
:type => :boolean
|
55
|
-
def preview
|
81
|
+
def preview list=:developer
|
56
82
|
require_relative 'preview'
|
57
|
-
Cli::Preview.invoke(email,
|
83
|
+
Cli::Preview.invoke(email, list, options)
|
58
84
|
end
|
59
85
|
|
60
86
|
desc 'scope [options]', 'Share this email using Litmus Scope (https://litmus.com/scope/)'
|
data/lib/inkcite/cli/preview.rb
CHANGED
@@ -4,47 +4,43 @@ module Inkcite
|
|
4
4
|
module Cli
|
5
5
|
class Preview
|
6
6
|
|
7
|
-
def self.invoke email,
|
7
|
+
def self.invoke email, list, opt
|
8
8
|
|
9
9
|
# Push the browser preview(s) up to the server to ensure that the
|
10
10
|
# latest images and "view in browser" versions are available.
|
11
11
|
email.upload unless opt[:'no-upload']
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
# Ensure we're dealing with a symbol rather than string.
|
14
|
+
list = list.to_sym
|
15
15
|
|
16
|
-
|
17
|
-
# explode those into an array for convenience. Email is already
|
18
|
-
# hard enough.
|
19
|
-
if also.any? { |a| a.match(',') }
|
20
|
-
also = also.collect { |a| a.split(',') }.flatten
|
16
|
+
preview_opt = {}
|
21
17
|
|
22
|
-
|
23
|
-
# to inject the new array of recipients back into it.
|
24
|
-
opt = opt.dup
|
25
|
-
opt[:also] = also
|
26
|
-
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
case to.to_sym
|
18
|
+
case list
|
31
19
|
when :client
|
32
|
-
|
20
|
+
preview_opt[:tag] = 'Preview'
|
21
|
+
preview_opt[:bcc] = true
|
33
22
|
when :internal
|
34
|
-
|
23
|
+
preview_opt[:tag] = 'Internal Preview'
|
24
|
+
preview_opt[:bcc] = true
|
35
25
|
when :developer
|
36
|
-
|
26
|
+
preview_opt[:tag] = 'Developer Test'
|
37
27
|
else
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
28
|
+
preview_opt[:tag] = "#{list.to_s.titleize} Test"
|
29
|
+
preview_opt[:bcc] = true
|
30
|
+
# abort <<-USAGE.strip_heredoc
|
31
|
+
#
|
32
|
+
# Oops! Inkcite doesn't recognize that distribution list. It needs
|
33
|
+
# to be one of 'client', 'internal' or 'developer':
|
34
|
+
#
|
35
|
+
# inkcite preview internal
|
36
|
+
#
|
37
|
+
# USAGE
|
38
|
+
#
|
39
|
+
# return
|
46
40
|
end
|
47
41
|
|
42
|
+
Mailer.send_to_list email, list, opt.merge(preview_opt)
|
43
|
+
|
48
44
|
end
|
49
45
|
|
50
46
|
end
|
data/lib/inkcite/cli/server.rb
CHANGED
@@ -11,10 +11,8 @@ module Inkcite
|
|
11
11
|
|
12
12
|
def self.start email, opts
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
puts 'Documentation available at http://inkcite.readme.io'
|
17
|
-
puts
|
14
|
+
Util.log "Inkcite #{Inkcite::VERSION} is starting up ..."
|
15
|
+
Util.log 'Documentation available at http://inkcite.readme.io'
|
18
16
|
|
19
17
|
# Read the hostname and port from the opts provided on the command
|
20
18
|
# line - or inherit the default of localhost:4567
|
@@ -58,10 +56,11 @@ module Inkcite
|
|
58
56
|
run InkciteApp.new(email, opts)
|
59
57
|
end
|
60
58
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
59
|
+
Util.log ''
|
60
|
+
Util.log "Your email is being served at http://#{host}:#{port}"
|
61
|
+
Util.log "Point your mobile device to http://#{ip}:#{port}" if ip
|
62
|
+
Util.log 'Press CTRL-C to exit server mode'
|
63
|
+
Util.log ''
|
65
64
|
|
66
65
|
begin
|
67
66
|
|
@@ -109,11 +108,15 @@ module Inkcite
|
|
109
108
|
# Minify the image if the source version in images/ is newer
|
110
109
|
# or if the configuration file controlling optimization has
|
111
110
|
# been updated since the last time the image was requested.
|
112
|
-
|
111
|
+
Image::ImageMinifier.minify(@email, File.basename(path), false) if can_serve(path)
|
113
112
|
|
114
113
|
# Let the super method handle the actual serving of the image.
|
115
|
-
super
|
114
|
+
res = super
|
115
|
+
|
116
|
+
# Install cache control into the response. Tried using
|
117
|
+
res[1][Rack::CACHE_CONTROL] = NO_CACHE
|
116
118
|
|
119
|
+
res
|
117
120
|
end
|
118
121
|
|
119
122
|
end
|
@@ -136,6 +139,11 @@ module Inkcite
|
|
136
139
|
response = Rack::Response.new
|
137
140
|
response[Rack::CONTENT_TYPE] = 'text/html'
|
138
141
|
|
142
|
+
# Speedup for local development ensuring that a substantial number of reloads
|
143
|
+
# (generated when developing multi-version emails simultaneously) can cause
|
144
|
+
# the browser to slow down.
|
145
|
+
response[Rack::CACHE_CONTROL] = NO_CACHE
|
146
|
+
|
139
147
|
begin
|
140
148
|
|
141
149
|
# Allow the designer to specify both short- and long-form versions of
|
@@ -146,12 +154,7 @@ module Inkcite
|
|
146
154
|
format = Util.detect(params['f'], params['format'], @opts[:format])
|
147
155
|
version = Util.detect(params['v'], params['version'], @opts[:version])
|
148
156
|
|
149
|
-
|
150
|
-
# messages are associated with this reload.
|
151
|
-
ts = "[#{Time.now.strftime(DATEFORMAT)}]"
|
152
|
-
|
153
|
-
puts ''
|
154
|
-
puts "#{ts} Rendering your email [environment=#{environment}, format=#{format}, version=#{version || 'default'}]"
|
157
|
+
Util.log "Rendering your email", :environment => environment, :format => format, :version => version || 'default'
|
155
158
|
|
156
159
|
view = @email.view(environment, format, version)
|
157
160
|
|
@@ -163,8 +166,8 @@ module Inkcite
|
|
163
166
|
|
164
167
|
unless view.errors.blank?
|
165
168
|
error_count = view.errors.count
|
166
|
-
|
167
|
-
|
169
|
+
Util.log "#{error_count} error#{'s' if error_count > 1} or warning#{'s' if error_count > 1}:"
|
170
|
+
view.errors.each { |e| Util.log(e) }
|
168
171
|
end
|
169
172
|
|
170
173
|
response.write html
|
@@ -186,7 +189,7 @@ module Inkcite
|
|
186
189
|
|
187
190
|
REQUEST_ROOT = '/'
|
188
191
|
|
189
|
-
|
192
|
+
NO_CACHE = 'no-cache, no-store'
|
190
193
|
|
191
194
|
end
|
192
195
|
end
|
data/lib/inkcite/cli/test.rb
CHANGED
data/lib/inkcite/email.rb
CHANGED
@@ -24,7 +24,11 @@ module Inkcite
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def config
|
27
|
-
Util.read_yml(
|
27
|
+
Util.read_yml(config_file, :fail_if_not_exists => true)
|
28
|
+
end
|
29
|
+
|
30
|
+
def config_file
|
31
|
+
File.join(path, 'config.yml')
|
28
32
|
end
|
29
33
|
|
30
34
|
def formats env=nil
|
@@ -57,12 +61,12 @@ module Inkcite
|
|
57
61
|
# Optimizes this email's images if optimize-images is enabled
|
58
62
|
# in the email configuration.
|
59
63
|
def optimize_images
|
60
|
-
|
64
|
+
Image::ImageMinifier.minify_all(self, false) if optimize_images?
|
61
65
|
end
|
62
66
|
|
63
67
|
# Optimizes all of the images in this email.
|
64
68
|
def optimize_images!
|
65
|
-
|
69
|
+
Image::ImageMinifier.minify_all(self, true)
|
66
70
|
end
|
67
71
|
|
68
72
|
def optimize_images?
|
@@ -72,7 +76,7 @@ module Inkcite
|
|
72
76
|
# Returns the directory that optimized, compressed images
|
73
77
|
# have been saved to.
|
74
78
|
def optimized_image_dir
|
75
|
-
File.join(path, optimize_images??
|
79
|
+
File.join(path, optimize_images?? Image::ImageMinifier::IMAGE_CACHE : IMAGES)
|
76
80
|
end
|
77
81
|
|
78
82
|
def project_file file
|
@@ -36,6 +36,10 @@ module Inkcite
|
|
36
36
|
EASE_IN_OUT = 'ease-in-out'
|
37
37
|
EASE_OUT = 'ease-out'
|
38
38
|
|
39
|
+
# Advanced easing functions courtesy of https://matthewlein.com/ceaser/
|
40
|
+
EASE_IN_CUBIC = 'cubic-bezier(0.550, 0.055, 0.675, 0.190)'
|
41
|
+
EASE_OUT_QUART = 'cubic-bezier(0.165, 0.840, 0.440, 1.000)'
|
42
|
+
|
39
43
|
# Animation name, view context and array of keyframes
|
40
44
|
attr_reader :name, :ctx
|
41
45
|
|
@@ -9,11 +9,15 @@ module Inkcite
|
|
9
9
|
# of 19.9% would render as 25%, 39.9% { ... }
|
10
10
|
attr_accessor :duration
|
11
11
|
|
12
|
+
# Alternative to duration, the ending percentage
|
13
|
+
attr_accessor :end_percent
|
14
|
+
|
12
15
|
def initialize percent, ctx, styles={}
|
13
16
|
|
14
17
|
# Animation percents are always rounded to the nearest whole number.
|
15
|
-
@percent = percent
|
16
|
-
@
|
18
|
+
@percent = percent
|
19
|
+
@end_percent = nil
|
20
|
+
@duration = nil
|
17
21
|
|
18
22
|
# Instantiate a new Style for this percentage.
|
19
23
|
@style = Inkcite::Renderer::Style.new(nil, ctx, styles)
|
@@ -55,7 +59,10 @@ module Inkcite
|
|
55
59
|
|
56
60
|
def to_css prefix
|
57
61
|
css = "#{@percent}%"
|
58
|
-
|
62
|
+
|
63
|
+
ends_at = calc_ends_at
|
64
|
+
css << ", #{ends_at}%" if ends_at
|
65
|
+
|
59
66
|
css << ' { '
|
60
67
|
css << @style.to_inline_css(prefix)
|
61
68
|
css << ' }'
|
@@ -64,6 +71,22 @@ module Inkcite
|
|
64
71
|
|
65
72
|
private
|
66
73
|
|
74
|
+
# Returns the percent at which the animation keyframe ends
|
75
|
+
# based on either end_percent (preferred) or duration (deprecated)
|
76
|
+
# being set. Will return nil if neither is present.
|
77
|
+
def calc_ends_at
|
78
|
+
ends_at = if @end_percent
|
79
|
+
@end_percent
|
80
|
+
elsif @duration
|
81
|
+
(@percent + @duration).round(1)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Ensure that the ending percentage never exceeds 100%
|
85
|
+
ends_at = 100 if ends_at && ends_at >= 100.0
|
86
|
+
|
87
|
+
ends_at
|
88
|
+
end
|
89
|
+
|
67
90
|
# Creates a copy of the array of styles with the appropriate
|
68
91
|
# properties (e.g. transform) prefixed.
|
69
92
|
def get_prefixed_styles prefix
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Inkcite
|
2
|
+
module Image
|
3
|
+
class ImageMinifier
|
4
|
+
|
5
|
+
# Base class for all image minifiers in the optimization pipeline
|
6
|
+
class Base
|
7
|
+
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
def initialize name
|
11
|
+
@name = name
|
12
|
+
end
|
13
|
+
|
14
|
+
def minify! email, source_img, cache_img
|
15
|
+
raise 'The extending class must implement this method'
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
# Common configuration names
|
21
|
+
JPG_QUALITY = :'jpg-quality'
|
22
|
+
|
23
|
+
# JPG quality bounds
|
24
|
+
MIN_QUALITY = 0
|
25
|
+
MAX_QUALITY = 100
|
26
|
+
|
27
|
+
def get_jpg_quality config, override_key, default
|
28
|
+
quality = (config[override_key] || config[JPG_QUALITY] || default).to_i
|
29
|
+
quality = MIN_QUALITY if quality < MIN_QUALITY
|
30
|
+
quality = MAX_QUALITY if quality > MAX_QUALITY
|
31
|
+
quality
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Inkcite
|
2
|
+
module Image
|
3
|
+
class GuetzliMinifier < ImageMinifier::Base
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
super('Guetzli')
|
7
|
+
end
|
8
|
+
|
9
|
+
def minify! email, source_img, cache_img
|
10
|
+
|
11
|
+
# Grab the full path to the guetzli binary
|
12
|
+
guetzli_path = `which guetzli`.delete("\n")
|
13
|
+
unless guetzli_path.blank?
|
14
|
+
|
15
|
+
cmd = []
|
16
|
+
cmd << guetzli_path
|
17
|
+
|
18
|
+
config = email.config
|
19
|
+
|
20
|
+
quality = get_jpg_quality(config, GUETZLI_QUALITY, DEFAULT_QUALITY)
|
21
|
+
if quality > 0 && quality < MAX_QUALITY
|
22
|
+
|
23
|
+
# Per the Guetzli documentation, a value less than 84 isn't useful.
|
24
|
+
quality = MIN_GUETZLI_QUALITY if quality < MIN_GUETZLI_QUALITY
|
25
|
+
cmd << "--quality #{quality}"
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
cmd << %Q("#{source_img}")
|
30
|
+
cmd << %Q("#{cache_img}")
|
31
|
+
|
32
|
+
Util::exec(cmd)
|
33
|
+
|
34
|
+
true
|
35
|
+
|
36
|
+
else
|
37
|
+
|
38
|
+
# No guetzli, so simply move the source image into the destination
|
39
|
+
# position without compression.
|
40
|
+
FileUtils.copy(source_img, cache_img)
|
41
|
+
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# Default quality is zero - which lets Guetzli decide how best to
|
51
|
+
# optimize the image.
|
52
|
+
DEFAULT_QUALITY = 0
|
53
|
+
|
54
|
+
# The minimum quality setting per the Guetzli runtime.
|
55
|
+
MIN_GUETZLI_QUALITY = 84
|
56
|
+
|
57
|
+
# Configuration field names
|
58
|
+
GUETZLI_QUALITY = :'guetzli-quality'
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|