inkcite 1.11.0 → 1.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +2 -2
- data/assets/init/helpers.tsv +7 -0
- data/assets/social/facebook.png +0 -0
- data/assets/social/pintrest.png +0 -0
- data/assets/social/twitter.png +0 -0
- data/inkcite.gemspec +5 -4
- data/lib/inkcite.rb +17 -6
- data/lib/inkcite/animation.rb +135 -0
- data/lib/inkcite/cli/base.rb +5 -14
- data/lib/inkcite/cli/build.rb +3 -3
- data/lib/inkcite/cli/init.rb +3 -3
- data/lib/inkcite/cli/preview.rb +25 -1
- data/lib/inkcite/cli/server.rb +1 -1
- data/lib/inkcite/cli/validate.rb +2 -11
- data/lib/inkcite/email.rb +1 -1
- data/lib/inkcite/mailer.rb +5 -0
- data/lib/inkcite/minifier.rb +58 -11
- data/lib/inkcite/renderer.rb +10 -2
- data/lib/inkcite/renderer/base.rb +45 -3
- data/lib/inkcite/renderer/button.rb +16 -12
- data/lib/inkcite/renderer/container_base.rb +14 -4
- data/lib/inkcite/renderer/element.rb +13 -3
- data/lib/inkcite/renderer/image.rb +46 -19
- data/lib/inkcite/renderer/image_base.rb +3 -3
- data/lib/inkcite/renderer/in_browser.rb +1 -1
- data/lib/inkcite/renderer/link.rb +91 -59
- data/lib/inkcite/renderer/lorem.rb +9 -1
- data/lib/inkcite/renderer/mobile_image.rb +3 -11
- data/lib/inkcite/renderer/mobile_only.rb +48 -0
- data/lib/inkcite/renderer/outlook_background.rb +61 -13
- data/lib/inkcite/renderer/property.rb +1 -1
- data/lib/inkcite/renderer/responsive.rb +10 -8
- data/lib/inkcite/renderer/snow.rb +20 -10
- data/lib/inkcite/renderer/social.rb +128 -0
- data/lib/inkcite/renderer/table.rb +13 -1
- data/lib/inkcite/renderer/table_base.rb +3 -3
- data/lib/inkcite/renderer/td.rb +32 -7
- data/lib/inkcite/renderer/video_preview.rb +257 -0
- data/lib/inkcite/uploader.rb +3 -3
- data/lib/inkcite/util.rb +19 -5
- data/lib/inkcite/version.rb +1 -1
- data/lib/inkcite/view.rb +29 -18
- data/lib/inkcite/view/context.rb +30 -0
- data/test/animation_spec.rb +38 -0
- data/test/email_spec.rb +0 -4
- data/test/minifier_spec.rb +243 -4
- data/test/parser_spec.rb +0 -4
- data/test/project/helpers.tsv +3 -0
- data/test/renderer/button_spec.rb +15 -13
- data/test/renderer/div_spec.rb +13 -4
- data/test/renderer/element_spec.rb +1 -5
- data/test/renderer/footnote_spec.rb +0 -4
- data/test/renderer/image_spec.rb +27 -11
- data/test/renderer/link_spec.rb +14 -4
- data/test/renderer/lorem_spec.rb +0 -4
- data/test/renderer/mobile_image_spec.rb +3 -11
- data/test/renderer/mobile_only_spec.rb +21 -0
- data/test/renderer/mobile_style_spec.rb +1 -5
- data/test/renderer/outlook_background_spec.rb +61 -0
- data/test/renderer/redacted_spec.rb +0 -4
- data/test/renderer/social_spec.rb +53 -0
- data/test/renderer/span_spec.rb +0 -4
- data/test/renderer/table_spec.rb +8 -4
- data/test/renderer/td_spec.rb +0 -4
- data/test/renderer/video_preview_spec.rb +19 -0
- data/test/renderer_spec.rb +0 -4
- data/test/test_helper.rb +7 -0
- data/test/view_spec.rb +12 -4
- metadata +89 -56
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c14c10f673644c60a3e92d4c511858d562c16f58
|
4
|
+
data.tar.gz: 0690d93ebed3be3f26735c9e6ecdd70301936a43
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2553f347fb054d2cf5ab68be3696a1223eabda24b7f1196d09871c3068c6cab2ccdda81214b8890720f8bf9463bd560d9093bee9f4db9d9c2e1aeaae1f240f30
|
7
|
+
data.tar.gz: 62224686033d05c4587995d4c92268287fac082a16013f54d71d9f185d5fb98ca7afbc54d14b9576170c24d4792069cfa0478841448cab82ec29e77296f9bb37
|
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@ require "bundler/gem_tasks"
|
|
2
2
|
require 'rake/testtask'
|
3
3
|
|
4
4
|
Rake::TestTask.new do |t|
|
5
|
-
t.libs.push
|
6
|
-
t.test_files = FileList['test/*_spec.rb', 'test/renderer/*_spec.rb']
|
5
|
+
t.libs.push 'lib'
|
6
|
+
t.test_files = FileList['test/test_helper.rb', 'test/*_spec.rb', 'test/renderer/*_spec.rb']
|
7
7
|
t.verbose = false
|
8
8
|
end
|
data/assets/init/helpers.tsv
CHANGED
@@ -15,3 +15,10 @@ title Welcome to Inkcite
|
|
15
15
|
|
16
16
|
// This defines the default font family used throughout your email.
|
17
17
|
font-family sans-serif
|
18
|
+
|
19
|
+
// Defaults for all buttons in the email
|
20
|
+
button-border 2px solid #0099cc
|
21
|
+
button-border-radius 5
|
22
|
+
button-color #99ffff
|
23
|
+
button-float center
|
24
|
+
button-padding 8
|
Binary file
|
Binary file
|
Binary file
|
data/inkcite.gemspec
CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
|
26
26
|
spec.add_dependency 'activesupport'
|
27
27
|
spec.add_dependency 'builder'
|
28
|
+
spec.add_dependency 'chunky_png'
|
28
29
|
spec.add_dependency 'erubis'
|
29
30
|
spec.add_dependency 'faker'
|
30
31
|
spec.add_dependency 'guard'
|
@@ -32,19 +33,19 @@ Gem::Specification.new do |spec|
|
|
32
33
|
spec.add_dependency 'htmlbeautifier'
|
33
34
|
spec.add_dependency 'image_optim'
|
34
35
|
spec.add_dependency 'image_optim_pack'
|
36
|
+
spec.add_dependency 'listen'
|
35
37
|
spec.add_dependency 'litmus'
|
36
38
|
spec.add_dependency 'mail'
|
37
39
|
spec.add_dependency 'mailgun-ruby'
|
38
40
|
spec.add_dependency 'net-sftp'
|
39
|
-
spec.add_dependency 'nokogiri'
|
40
41
|
spec.add_dependency 'rack'
|
41
42
|
spec.add_dependency 'rack-livereload'
|
42
43
|
spec.add_dependency 'rubyzip'
|
43
44
|
spec.add_dependency 'thor'
|
44
45
|
spec.add_dependency 'yui-compressor'
|
45
46
|
|
46
|
-
spec.add_development_dependency
|
47
|
-
spec.add_development_dependency
|
48
|
-
spec.add_development_dependency
|
47
|
+
spec.add_development_dependency 'bundler'
|
48
|
+
spec.add_development_dependency 'rake'
|
49
|
+
spec.add_development_dependency 'minitest'
|
49
50
|
|
50
51
|
end
|
data/lib/inkcite.rb
CHANGED
@@ -1,9 +1,19 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
require 'active_support/core_ext/kernel/reporting.rb' # silence_warnings
|
2
|
+
|
3
|
+
# Need to silence warnings when we import these other gems as
|
4
|
+
# there are numerous messages produced as a result of circular
|
5
|
+
# dependencies and other problems within these gems, outside
|
6
|
+
# of my control.
|
7
|
+
silence_warnings do
|
8
|
+
require 'csv'
|
9
|
+
require 'erubis'
|
10
|
+
require 'i18n'
|
11
|
+
require 'image_optim'
|
12
|
+
require 'set'
|
13
|
+
require 'uri'
|
14
|
+
require 'yaml'
|
15
|
+
require 'yui/compressor'
|
16
|
+
end
|
7
17
|
|
8
18
|
require 'active_support/core_ext/hash/keys.rb' # Symbolize keys!
|
9
19
|
require 'active_support/core_ext/module/delegation.rb'
|
@@ -19,6 +29,7 @@ require 'inkcite/view'
|
|
19
29
|
require 'inkcite/minifier'
|
20
30
|
require 'inkcite/parser'
|
21
31
|
require 'inkcite/renderer'
|
32
|
+
require 'inkcite/animation'
|
22
33
|
|
23
34
|
module Inkcite
|
24
35
|
|
@@ -0,0 +1,135 @@
|
|
1
|
+
module Inkcite
|
2
|
+
module Animation
|
3
|
+
|
4
|
+
class Keyframe
|
5
|
+
|
6
|
+
attr_reader :percent
|
7
|
+
|
8
|
+
def initialize percent, styles={}
|
9
|
+
# Animation percents are always rounded to the nearest whole number.
|
10
|
+
@percent = percent.round(0)
|
11
|
+
@styles = styles
|
12
|
+
end
|
13
|
+
|
14
|
+
def [] key
|
15
|
+
@styles[key]
|
16
|
+
end
|
17
|
+
|
18
|
+
def []= key, val
|
19
|
+
@styles[key] = val
|
20
|
+
end
|
21
|
+
|
22
|
+
def add key, val
|
23
|
+
self[key] = val
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_with_prefixes key, val, ctx
|
28
|
+
|
29
|
+
Animation.get_prefixes(ctx).each do |prefix|
|
30
|
+
_key = "#{prefix}#{key}".to_sym
|
31
|
+
self[_key] = val
|
32
|
+
end
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
|
38
|
+
css = ''
|
39
|
+
css << " #{@percent}%"
|
40
|
+
css << ' ' * (7 - css.length)
|
41
|
+
css << '{ '
|
42
|
+
css << Renderer.render_styles(@styles)
|
43
|
+
css << ' }'
|
44
|
+
|
45
|
+
css
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
class Keyframes
|
51
|
+
|
52
|
+
def initialize name, context
|
53
|
+
@name = name
|
54
|
+
@ctx = context
|
55
|
+
@keyframes = []
|
56
|
+
end
|
57
|
+
|
58
|
+
def << keyframe
|
59
|
+
@keyframes << keyframe
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_keyframe percent, styles
|
63
|
+
self << Keyframe.new(percent, styles)
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_s
|
67
|
+
|
68
|
+
css = ''
|
69
|
+
|
70
|
+
keyframe_css = @keyframes.sort { |kf1,kf2| kf1.percent <=> kf2.percent }.collect(&:to_s).join("\n")
|
71
|
+
|
72
|
+
prefixes = Animation.get_prefixes(@ctx)
|
73
|
+
|
74
|
+
prefixes.each do |prefix|
|
75
|
+
css << "@#{prefix}keyframes #{@name} {\n"
|
76
|
+
css << keyframe_css
|
77
|
+
css << "\n}\n"
|
78
|
+
end
|
79
|
+
|
80
|
+
css
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.get_prefixes ctx
|
86
|
+
ALL_BROWSERS
|
87
|
+
end
|
88
|
+
|
89
|
+
# True if we're limiting the animation to webkit only. In development
|
90
|
+
# or in the browser version of the email, the animation should be as
|
91
|
+
# compatible as possible but in all other cases it should be webkit only.
|
92
|
+
def self.webkit_only? ctx
|
93
|
+
false #&& !(ctx.development? || ctx.browser?)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Renders the CSS with the appropriate browser prefixes based
|
97
|
+
# on whether or not this version of the email is webkit only.
|
98
|
+
def self.with_browser_prefixes css, ctx, opts={}
|
99
|
+
|
100
|
+
indentation = opts[:indentation] || ''
|
101
|
+
|
102
|
+
# Convert an integer indentation value into that number of spaces.
|
103
|
+
indentation = ' ' * indentation if indentation.is_a?(Integer)
|
104
|
+
|
105
|
+
separator = opts[:separator] || "\n"
|
106
|
+
|
107
|
+
# Determine which prefixes will be applied.
|
108
|
+
browser_prefixes = webkit_only?(ctx) ? WEBKIT_BROWSERS : ALL_BROWSERS
|
109
|
+
|
110
|
+
# This will hold the completed CSS with all prefixes applied.
|
111
|
+
_css = ''
|
112
|
+
|
113
|
+
# Iterate through the prefixes and apply them with the indentation
|
114
|
+
# and CSS declaration with line breaks.
|
115
|
+
browser_prefixes.each do |prefix|
|
116
|
+
_css << indentation
|
117
|
+
_css << prefix
|
118
|
+
_css << css
|
119
|
+
_css << separator
|
120
|
+
end
|
121
|
+
|
122
|
+
_css
|
123
|
+
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
|
128
|
+
# Static arrays with browser prefixes. Turns out that Firefox, IE and Opera
|
129
|
+
# don't require a prefix so to target everything we need the non-prefixed version
|
130
|
+
# (hence the blank entry) plus the webkit prefix.
|
131
|
+
WEBKIT_BROWSERS = ['-webkit-']
|
132
|
+
ALL_BROWSERS = [''] + WEBKIT_BROWSERS
|
133
|
+
|
134
|
+
end
|
135
|
+
end
|
data/lib/inkcite/cli/base.rb
CHANGED
@@ -45,6 +45,10 @@ module Inkcite
|
|
45
45
|
option :version,
|
46
46
|
:aliases => '-v',
|
47
47
|
:desc => 'Preview a specific version of the email'
|
48
|
+
option :also,
|
49
|
+
:aliases => '-a',
|
50
|
+
:desc => 'Add one or more (space-separated) recipients to this specific mailing',
|
51
|
+
:type => :array
|
48
52
|
def preview to=:developer
|
49
53
|
require_relative 'preview'
|
50
54
|
Cli::Preview.invoke(email, to, options)
|
@@ -75,7 +79,7 @@ module Inkcite
|
|
75
79
|
:desc => 'The ip address Inkcite will bind to'
|
76
80
|
method_option :port,
|
77
81
|
:aliases => '-p',
|
78
|
-
:default =>
|
82
|
+
:default => 4567,
|
79
83
|
:desc => 'The port Inkcite will listen on',
|
80
84
|
:type => :numeric
|
81
85
|
option :version,
|
@@ -113,19 +117,6 @@ module Inkcite
|
|
113
117
|
options[:force] ? email.upload! : email.upload
|
114
118
|
end
|
115
119
|
|
116
|
-
desc 'validate', 'Validate the email against W3C standards'
|
117
|
-
option :environment,
|
118
|
-
:aliases => '-e',
|
119
|
-
:default => 'production',
|
120
|
-
:desc => 'The environment (production, preview, development) to be Inkcite will run under'
|
121
|
-
option :version,
|
122
|
-
:aliases => '-v',
|
123
|
-
:desc => 'Preview a specific version of the email'
|
124
|
-
def validate
|
125
|
-
require_relative 'validate'
|
126
|
-
Cli::Validate.invoke(email, options)
|
127
|
-
end
|
128
|
-
|
129
120
|
private
|
130
121
|
|
131
122
|
# Resolves the desired environment (e.g. :development or :preview)
|
data/lib/inkcite/cli/build.rb
CHANGED
@@ -45,7 +45,7 @@ module Inkcite
|
|
45
45
|
|
46
46
|
# The Zip::File will try to update an existing archive so just blow the old
|
47
47
|
# one away if it still exists.
|
48
|
-
File.delete(zip_file) if File.
|
48
|
+
File.delete(zip_file) if File.exist?(zip_file)
|
49
49
|
|
50
50
|
# The absolute path to the build directories
|
51
51
|
build_html_to = build_path(email)
|
@@ -54,7 +54,7 @@ module Inkcite
|
|
54
54
|
Zip::File.open(zip_file, Zip::File::CREATE) do |zip|
|
55
55
|
|
56
56
|
# Add the minified images to the .zip archive
|
57
|
-
if File.
|
57
|
+
if File.exist?(build_images_to)
|
58
58
|
Dir.foreach(build_images_to) do |img|
|
59
59
|
img_path = File.join(build_images_to, img)
|
60
60
|
zip.add(File.join(Inkcite::Email::IMAGES, img), img_path) unless File.directory?(img_path)
|
@@ -113,7 +113,7 @@ module Inkcite
|
|
113
113
|
# Copy all of the source images into the build directory in preparation
|
114
114
|
# for optimization
|
115
115
|
build_images_from = email.optimized_image_dir
|
116
|
-
FileUtils.cp_r(File.join(build_images_from, '.'), build_images_to) if File.
|
116
|
+
FileUtils.cp_r(File.join(build_images_from, '.'), build_images_to) if File.exist?(build_images_from)
|
117
117
|
|
118
118
|
end
|
119
119
|
|
data/lib/inkcite/cli/init.rb
CHANGED
@@ -8,7 +8,7 @@ module Inkcite
|
|
8
8
|
|
9
9
|
# Sanity check to make sure we're not writing over an existing
|
10
10
|
# Inkcite project.
|
11
|
-
abort "It appears that an Inkcite already exists in #{path}" if File.
|
11
|
+
abort "It appears that an Inkcite already exists in #{path}" if File.exist?(File.join(full_init_path, 'config.yml'))
|
12
12
|
|
13
13
|
# Check to see if the user specified a --from path that is used to
|
14
14
|
# clone an existing project rather than init a new one.
|
@@ -41,7 +41,7 @@ module Inkcite
|
|
41
41
|
|
42
42
|
# Verify that the source directory contains the config.yml file
|
43
43
|
# signifying an existing Inkcite project.
|
44
|
-
abort "Can't find #{from_path} or it isn't an existing Inkcite project" unless File.
|
44
|
+
abort "Can't find #{from_path} or it isn't an existing Inkcite project" unless File.exist?(File.join(from_path, 'config.yml'))
|
45
45
|
|
46
46
|
# Copy the main Inkcite project files
|
47
47
|
Dir.glob(File.join(from_path, '*.{html,tsv,txt,yml}')).each do |from_file|
|
@@ -59,7 +59,7 @@ module Inkcite
|
|
59
59
|
|
60
60
|
# Check to see if there are images and copy those as well.
|
61
61
|
from_path = File.join(from_path, Inkcite::Email::IMAGES)
|
62
|
-
if File.
|
62
|
+
if File.exist?(from_path)
|
63
63
|
FileUtils.cp_r(File.join(from_path, '.'), full_init_image_path)
|
64
64
|
puts "Copied images to #{init_image_path}"
|
65
65
|
end
|
data/lib/inkcite/cli/preview.rb
CHANGED
@@ -10,6 +10,23 @@ module Inkcite
|
|
10
10
|
# latest images and "view in browser" versions are available.
|
11
11
|
email.upload
|
12
12
|
|
13
|
+
also = opt[:also]
|
14
|
+
unless also.blank?
|
15
|
+
|
16
|
+
# Sometimes people use commas to separate the --also addresses so
|
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
|
21
|
+
|
22
|
+
# Since opt is frozen by Thor we need to make a copy of it in order
|
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
|
+
|
13
30
|
case to.to_sym
|
14
31
|
when :client
|
15
32
|
Inkcite::Mailer.client(email, opt)
|
@@ -18,7 +35,14 @@ module Inkcite
|
|
18
35
|
when :developer
|
19
36
|
Inkcite::Mailer.developer(email, opt)
|
20
37
|
else
|
21
|
-
|
38
|
+
abort <<-USAGE.strip_heredoc
|
39
|
+
|
40
|
+
Oops! Inkcite doesn't recognize that distribution list. It needs
|
41
|
+
to be one of 'client', 'internal' or 'developer':
|
42
|
+
|
43
|
+
inkcite preview internal
|
44
|
+
|
45
|
+
USAGE
|
22
46
|
end
|
23
47
|
|
24
48
|
end
|
data/lib/inkcite/cli/server.rb
CHANGED
data/lib/inkcite/cli/validate.rb
CHANGED
@@ -20,28 +20,19 @@ module Inkcite
|
|
20
20
|
# The version of the email we will be sending.
|
21
21
|
view = email.view(environment, :email, version)
|
22
22
|
|
23
|
-
# Always disable minification
|
24
|
-
view.config[:minify] = false
|
25
|
-
|
26
23
|
subject = view.subject
|
27
24
|
|
28
25
|
print "Validating '#{subject}' ... "
|
29
26
|
|
30
|
-
|
31
|
-
|
32
|
-
validator = Nokogiri::HTML(source) do |config|
|
27
|
+
validator = Nokogiri::HTML(view.render!) do |config|
|
33
28
|
config.strict
|
34
29
|
end
|
35
30
|
|
36
31
|
if validator.errors.any?
|
37
32
|
puts 'Invalid!'
|
38
|
-
|
39
|
-
lines = source.split(/\n/)
|
40
|
-
|
41
33
|
validator.errors.each do |err|
|
42
34
|
puts err.inspect
|
43
|
-
puts
|
44
|
-
puts [ err.column, err.int1, err.str1, err.str2, err.str3 ].inspect
|
35
|
+
puts err.line
|
45
36
|
end
|
46
37
|
|
47
38
|
else
|
data/lib/inkcite/email.rb
CHANGED
data/lib/inkcite/mailer.rb
CHANGED
@@ -64,6 +64,11 @@ module Inkcite
|
|
64
64
|
# Sends each version of the provided email with the indicated options.
|
65
65
|
def self.send email, opts
|
66
66
|
|
67
|
+
# Check to see if additional one-time recipients have been added
|
68
|
+
# to the command line.
|
69
|
+
also_to = opts[:also]
|
70
|
+
opts[:cc] = [*opts[:cc]] + also_to unless also_to.blank?
|
71
|
+
|
67
72
|
# Check to see if a specific version is requested or if unspecified
|
68
73
|
# all versions of the email should be sent.
|
69
74
|
versions = Array(opts[:version] || email.versions)
|
data/lib/inkcite/minifier.rb
CHANGED
@@ -1,14 +1,60 @@
|
|
1
|
-
require 'image_optim'
|
2
|
-
require 'yui/compressor'
|
3
|
-
|
4
1
|
module Inkcite
|
5
2
|
class Minifier
|
6
3
|
|
7
4
|
# Directory of optimized images
|
8
5
|
IMAGE_CACHE = "images-optim"
|
9
6
|
|
7
|
+
# Maximum line length for CSS and HTML - lines exceeding this length cause
|
8
|
+
# problems in certain email clients.
|
9
|
+
MAXIMUM_LINE_LENGTH = 800
|
10
|
+
|
10
11
|
def self.css code, ctx
|
11
|
-
|
12
|
+
|
13
|
+
# Do nothing to the code unless minification is enabled.
|
14
|
+
if minify?(ctx)
|
15
|
+
|
16
|
+
# After YUI's CSS compressor started introducing problems into CSS3
|
17
|
+
# animations, I've switched to a homegrown, extremely simple compression
|
18
|
+
# algorithm for CSS. Instead of messing with parameters, we're simply
|
19
|
+
# eliminating whitespace.
|
20
|
+
|
21
|
+
# Replace all line breaks with spaces
|
22
|
+
code.gsub!(/[\n\r\f]/, ' ')
|
23
|
+
|
24
|
+
# Remove whitespace at the beginning or ending of the code
|
25
|
+
code.gsub!(/^\s+/, '')
|
26
|
+
code.gsub!(/\s+$/, '')
|
27
|
+
|
28
|
+
# Compress multiple whitespace characters into a single space.
|
29
|
+
code.gsub!(/\s{2,}/, ' ')
|
30
|
+
|
31
|
+
# Remove whitespace preceding or following open and close curly brackets.
|
32
|
+
code.gsub!(/\s*([{};:])\s*/, "\\1")
|
33
|
+
|
34
|
+
# Remove semicolons preceding close brackets.
|
35
|
+
code.gsub!(';}', '}')
|
36
|
+
|
37
|
+
# Certain versions of outlook have a problem with excessively long lines
|
38
|
+
# so if this minified code now exceeds the maximum line limit, re-introduce
|
39
|
+
# wrapping in spots where it won't break anything to do so - e.g. following
|
40
|
+
# a semicolon or close bracket.
|
41
|
+
if ctx.email? && code.length > MAXIMUM_LINE_LENGTH
|
42
|
+
|
43
|
+
# Position at which a line break will be inserted at.
|
44
|
+
break_at = 0
|
45
|
+
|
46
|
+
# Work through the code injecting line breaks until either no further
|
47
|
+
# breakable characters are found or we've reached the end of the code.
|
48
|
+
while break_at < code.length
|
49
|
+
break_at = code.rindex(/[;}]/, break_at + MAXIMUM_LINE_LENGTH) + 1
|
50
|
+
code.insert(break_at, "\n") if break_at && break_at < code.length
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
code
|
12
58
|
end
|
13
59
|
|
14
60
|
def self.html lines, ctx
|
@@ -72,7 +118,7 @@ module Inkcite
|
|
72
118
|
|
73
119
|
# If the image cache exists, we need to check to see if any images have been
|
74
120
|
# removed since the last build.
|
75
|
-
if File.
|
121
|
+
if File.exist?(cache_path)
|
76
122
|
|
77
123
|
# Get a list of the files in the cache that do not also exist in the
|
78
124
|
# project's images/ directory.
|
@@ -137,7 +183,7 @@ module Inkcite
|
|
137
183
|
end
|
138
184
|
|
139
185
|
def self.remove_comments html, ctx
|
140
|
-
|
186
|
+
remove_comments?(ctx) ? html.gsub(HTML_COMMENT_REGEX, '') : html
|
141
187
|
end
|
142
188
|
|
143
189
|
private
|
@@ -148,7 +194,6 @@ module Inkcite
|
|
148
194
|
IMAGE_OPTIM_CONFIG_YML = 'image_optim.yml'
|
149
195
|
|
150
196
|
NEW_LINE = "\n"
|
151
|
-
MAXIMUM_LINE_LENGTH = 800
|
152
197
|
|
153
198
|
# Used to match inline styles that will be compressed when minifying
|
154
199
|
# the entire email.
|
@@ -163,12 +208,14 @@ module Inkcite
|
|
163
208
|
ctx.is_enabled?(:minify)
|
164
209
|
end
|
165
210
|
|
166
|
-
|
167
|
-
|
211
|
+
# Config attribute that allows for comment striping to be disabled.
|
212
|
+
# e.g. strip-comments: false
|
213
|
+
def self.remove_comments? ctx
|
214
|
+
minify?(ctx) && !ctx.is_disabled?(:'strip-comments')
|
168
215
|
end
|
169
216
|
|
170
|
-
def self.
|
171
|
-
ctx.
|
217
|
+
def self.js_compressor ctx
|
218
|
+
ctx.js_compressor ||= YUI::JavaScriptCompressor.new(:munge => true)
|
172
219
|
end
|
173
220
|
|
174
221
|
end
|