inkcite 1.12.0 → 1.12.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/assets/builtin-helpers.tsv +9 -0
- data/lib/inkcite/renderer/base.rb +1 -1
- data/lib/inkcite/renderer/image.rb +3 -9
- data/lib/inkcite/renderer/image_base.rb +9 -2
- data/lib/inkcite/renderer/link.rb +1 -1
- data/lib/inkcite/renderer/mobile_only.rb +2 -2
- data/lib/inkcite/renderer/outlook_background.rb +2 -2
- data/lib/inkcite/renderer/video_preview.rb +66 -49
- data/lib/inkcite/version.rb +1 -1
- data/lib/inkcite/view.rb +11 -9
- data/test/renderer/mobile_only_spec.rb +3 -3
- data/test/renderer/video_preview_spec.rb +12 -1
- data/test/view_spec.rb +12 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 729a1ea12dcb8c0180541d0b4aebb22346985f2f
|
4
|
+
data.tar.gz: c10280cade618463c9ecebe81e50b1acca46a49e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39f5ebde420c845be3b262d7b4266a491bed516f561a5679616bd4d235693adbba3c6990bdc9b51c61facb00dcfd35b418c2c2f7f3602f13f7daeb7de971bdf6
|
7
|
+
data.tar.gz: 2f8441f0f65e4faf1323229c30a8fbdd2ea4b31fc8cdc61f4a1520921bc23fb3cb6727e76cd898b104227f047a924d1af7150180dd8e152fa6e36d14c5ae586a
|
@@ -0,0 +1,9 @@
|
|
1
|
+
// Conditional helpers for inclusion or exclusion.
|
2
|
+
if <!--[if $test$]> <![endif]-->
|
3
|
+
if-not <!--[if !$test$]><!-- --> <!--<![endif]-->
|
4
|
+
|
5
|
+
// Predeclaring common inclusion and exclusion targets
|
6
|
+
not-outlook {if-not test=mso} {/if-not}
|
7
|
+
not-vml {if-not test=vml} {/if-not}
|
8
|
+
outlook-only {if test=mso} {/if}
|
9
|
+
vml-only {if test=vml} {/if}
|
@@ -84,10 +84,8 @@ module Inkcite
|
|
84
84
|
img[:src] = image_url(outlook_src, opt, ctx)
|
85
85
|
|
86
86
|
# Wrap the image in the outlook-specific conditionals.
|
87
|
-
html <<
|
88
|
-
html <<
|
89
|
-
html << '<![endif]-->'
|
90
|
-
html << '<!--[if !mso]><!-- -->'
|
87
|
+
html << if_mso(img)
|
88
|
+
html << '{not-outlook}'
|
91
89
|
|
92
90
|
end
|
93
91
|
|
@@ -137,7 +135,7 @@ module Inkcite
|
|
137
135
|
html << img.to_s
|
138
136
|
|
139
137
|
# Conclude the outlook-specific conditional if opened.
|
140
|
-
html << '
|
138
|
+
html << '{/not-outlook}' unless outlook_src.blank?
|
141
139
|
|
142
140
|
html
|
143
141
|
end
|
@@ -148,10 +146,6 @@ module Inkcite
|
|
148
146
|
# be copied to the title field.
|
149
147
|
COPY_ALT_TO_TITLE = :'copy-alt-to-title'
|
150
148
|
|
151
|
-
# Name of the property that allows an outlook-specific src to be specified
|
152
|
-
# for an image.
|
153
|
-
OUTLOOK_SRC = :'outlook-src'
|
154
|
-
|
155
149
|
end
|
156
150
|
end
|
157
151
|
end
|
@@ -4,6 +4,10 @@ module Inkcite
|
|
4
4
|
|
5
5
|
protected
|
6
6
|
|
7
|
+
# Name of the property that allows an outlook-specific src to be specified
|
8
|
+
# for an image.
|
9
|
+
OUTLOOK_SRC = :'outlook-src'
|
10
|
+
|
7
11
|
# Display mode constants
|
8
12
|
BLOCK = 'block'
|
9
13
|
DEFAULT = 'default'
|
@@ -12,7 +16,7 @@ module Inkcite
|
|
12
16
|
# For the given image source URL provided, returns either the fully-qualfied
|
13
17
|
# path to the image (via View's image_url method) or returns a placeholder
|
14
18
|
# if the image is missing.
|
15
|
-
def image_url _src, opt, ctx, assert_dimensions=true
|
19
|
+
def image_url _src, opt, ctx, assert_dimensions=true, add_quotes=true
|
16
20
|
|
17
21
|
src = _src
|
18
22
|
|
@@ -81,7 +85,10 @@ module Inkcite
|
|
81
85
|
# src so that we don't display the verbose qualified URL to the developer.
|
82
86
|
ctx.error('Missing image dimensions', { :src => _src }) if missing_dimensions && assert_dimensions
|
83
87
|
|
84
|
-
|
88
|
+
# If desired (and usually it is) wrap the src in quotes.
|
89
|
+
src = quote(src) if add_quotes
|
90
|
+
|
91
|
+
src
|
85
92
|
end
|
86
93
|
|
87
94
|
def klass_name src, ctx
|
@@ -115,7 +115,7 @@ module Inkcite
|
|
115
115
|
|
116
116
|
# Always duplicate the string provided just to make sure we're not
|
117
117
|
# modifying a frozen link or adding tagging to a previously tagged HREF.
|
118
|
-
href = href.dup
|
118
|
+
href = href.dup if href
|
119
119
|
|
120
120
|
# True if the href is missing. If so, we may try to look it up by it's ID
|
121
121
|
# or we'll insert a default TBD link.
|
@@ -16,7 +16,7 @@ module Inkcite
|
|
16
16
|
# Intentionally NOT using 'mso-hide: all' version as it requires all
|
17
17
|
# nested tables to have that attribute applied. Why have all that extra
|
18
18
|
# markup - just use this simple conditional instead.
|
19
|
-
html << '
|
19
|
+
html << '{if-not test="mso 9"}'
|
20
20
|
|
21
21
|
# These elements style the div such that it is invisible in all
|
22
22
|
# other major email clients.
|
@@ -36,7 +36,7 @@ module Inkcite
|
|
36
36
|
html << '</div>'
|
37
37
|
|
38
38
|
# Close the outlook conditional for the close tag.
|
39
|
-
html << '
|
39
|
+
html << '{/if-not}'
|
40
40
|
|
41
41
|
end
|
42
42
|
|
@@ -16,7 +16,7 @@ module Inkcite
|
|
16
16
|
# 'vml: false' in config.yml
|
17
17
|
return nil unless ctx.vml_enabled?
|
18
18
|
|
19
|
-
html = '
|
19
|
+
html = '{if test="gte mso 9"}'
|
20
20
|
|
21
21
|
if tag == '/outlook-bg'
|
22
22
|
html << '</div>'
|
@@ -86,7 +86,7 @@ module Inkcite
|
|
86
86
|
|
87
87
|
end
|
88
88
|
|
89
|
-
html << '
|
89
|
+
html << '{/if}'
|
90
90
|
|
91
91
|
html
|
92
92
|
end
|
@@ -3,7 +3,7 @@ module Inkcite
|
|
3
3
|
|
4
4
|
# Better video preview courtesy of @stigm
|
5
5
|
# https://medium.com/cm-engineering/better-video-previews-for-email-12432ce71846#.2o9qgc7hd
|
6
|
-
class VideoPreview <
|
6
|
+
class VideoPreview < ImageBase
|
7
7
|
|
8
8
|
def render tag, opt, ctx
|
9
9
|
|
@@ -40,15 +40,7 @@ module Inkcite
|
|
40
40
|
# this loop also verifies that the referenced image exists.
|
41
41
|
frame_count.times do |n|
|
42
42
|
frame_src = src.gsub('%1', "#{n + 1}")
|
43
|
-
|
44
|
-
# Check that non-fully-qualified images exist in the project's
|
45
|
-
# images/ directory.
|
46
|
-
unless Util::is_fully_qualified?(frame_src)
|
47
|
-
ctx.assert_image_exists(frame_src)
|
48
|
-
frame_src = ctx.image_url(frame_src)
|
49
|
-
end
|
50
|
-
|
51
|
-
frames << frame_src
|
43
|
+
frames << image_url(frame_src, opt, ctx, false, false)
|
52
44
|
end
|
53
45
|
|
54
46
|
# Grab the first fully-qualified frame
|
@@ -81,12 +73,22 @@ module Inkcite
|
|
81
73
|
# assigned to the table and defined in the CSS.
|
82
74
|
animation_name = "#{hover_klass}#{uid}-frames"
|
83
75
|
|
76
|
+
# Size calculations based on the specified arrow size or
|
77
|
+
# the defaulted 30px arrow. The border_* variables control
|
78
|
+
# the circular border around the play arrow.
|
79
|
+
play_arrow_size = (opt[PLAY_ARROW_SIZE] || 30).to_i
|
80
|
+
play_arrow_height = (play_arrow_size * 0.5666).round
|
81
|
+
play_border_radius = (play_arrow_size * 1.1333).round
|
82
|
+
play_border_top_bottom = (play_arrow_size * 0.6).round
|
83
|
+
play_border_right = (play_arrow_size * 0.5333).round
|
84
|
+
play_border_left = (play_arrow_size * 0.8).round
|
85
|
+
|
84
86
|
html = []
|
85
|
-
html << '
|
87
|
+
html << '{not-outlook}'
|
86
88
|
|
87
89
|
# Using an Element to produce the appropriate anchor helper with
|
88
90
|
# the desired
|
89
|
-
html << Element.new('a', { :id => id, :href => href, :class => hover_klass, :bgcolor => bgcolor, :bggradient => gradient, :block => true }).to_helper
|
91
|
+
html << Element.new('a', { :id => id, :href => quote(href), :class => hover_klass, :bgcolor => bgcolor, :bggradient => gradient, :block => true }).to_helper
|
90
92
|
|
91
93
|
table = Element.new('table', {
|
92
94
|
:width => '100%', :background => first_frame, BACKGROUND_SIZE => 'cover',
|
@@ -95,8 +97,6 @@ module Inkcite
|
|
95
97
|
table[:animation] = %Q("#{animation_name} #{duration}s ease infinite") if has_animation
|
96
98
|
html << table.to_helper
|
97
99
|
|
98
|
-
html << Element.new('td', :width => '25%').to_helper
|
99
|
-
|
100
100
|
# Transparent spacer for preserving aspect ratio.
|
101
101
|
spacer_image_name = "vp-#{scaled_width}x#{height}.png"
|
102
102
|
spacer_image = File.join(ctx.email.image_dir, spacer_image_name)
|
@@ -114,26 +114,18 @@ module Inkcite
|
|
114
114
|
|
115
115
|
end
|
116
116
|
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
120
|
-
|
121
|
-
|
122
|
-
:style => { :height => :auto, :opacity => 0, :visibility => :hidden } }).to_s
|
123
|
-
|
124
|
-
html <<
|
117
|
+
# Assembling the first <td> which manages the aspect ratio of the
|
118
|
+
# video as a separate string to avoid unnecessary line breaks in
|
119
|
+
# the resulting HTML.
|
120
|
+
aspect_ratio_td = Element.new('td', :width => '25%').to_helper
|
121
|
+
aspect_ratio_td << Element.new('img', { :src => ctx.image_url(spacer_image_name), :alt => quote(''), :width => '100%', :border => 0,
|
122
|
+
:style => { :height => :auto, :display => :block, :opacity => 0, :visibility => :hidden } }).to_s
|
123
|
+
aspect_ratio_td << '{/td}'
|
124
|
+
html << aspect_ratio_td
|
125
125
|
|
126
126
|
# Center column holds the CSS-based arrow
|
127
127
|
html << Element.new('td', :width => '50%', :align => :center, :valign => :middle).to_helper
|
128
128
|
|
129
|
-
play_arrow_size = (opt[PLAY_ARROW_SIZE] || 30).to_i
|
130
|
-
|
131
|
-
play_border_radius = (play_arrow_size * 1.1333).round
|
132
|
-
play_border_top_bottom = (play_arrow_size * 0.6).round
|
133
|
-
play_border_right = (play_arrow_size * 0.5333).round
|
134
|
-
play_border_left = (play_arrow_size * 0.8).round
|
135
|
-
play_arrow_height = (play_arrow_size * 0.5666).round
|
136
|
-
|
137
129
|
# These are the arrow and circle border, respectively. Not currently
|
138
130
|
# configurable in terms of size or color.
|
139
131
|
html << %Q(<div class="#{play_button_klass}" style="background-image: linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.1)); border: 4px solid white; border-radius: 50%; box-shadow: 0 1px 2px rgba(0,0,0,0.3), inset 0 1px 2px rgba(0,0,0,0.3); height: #{px(play_border_radius)}; margin: 0 auto; padding: #{px(play_border_top_bottom)} #{px(play_border_right)} #{px(play_border_top_bottom)} #{px(play_border_left)}; transition: transform .5s cubic-bezier(0.075, 0.82, 0.165, 1); width: #{px(play_border_radius)};">)
|
@@ -149,28 +141,53 @@ module Inkcite
|
|
149
141
|
# browser only loads the frames once the animation demands them.
|
150
142
|
if has_animation && !opt[NO_PRELOAD]
|
151
143
|
all_frames = frames.collect { |f| %Q(url(#{f})) }.join(',')
|
152
|
-
html << Element.new('div', :style => { BACKGROUND_IMAGE => %Q(
|
144
|
+
html << Element.new('div', :style => { BACKGROUND_IMAGE => %Q(#{all_frames}), :display => 'none' }).to_s + '</div>'
|
153
145
|
end
|
154
146
|
|
155
147
|
# Concludes the if [if !vml] section targeting non-outlook.
|
156
|
-
html << '
|
157
|
-
|
158
|
-
#
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
148
|
+
html << '{/not-outlook}'
|
149
|
+
|
150
|
+
# Check for the outlook-src attribute which will be used in place of
|
151
|
+
# the first frame if it is specified.
|
152
|
+
outlook_src = opt[OUTLOOK_SRC]
|
153
|
+
outlook_src = outlook_src.blank? ? first_frame : image_url(outlook_src, opt, ctx, false, false)
|
154
|
+
|
155
|
+
html << '{outlook-only}'
|
156
|
+
if ctx.vml_enabled?
|
157
|
+
|
158
|
+
# Calculations necessary to render the play arrow in VML.
|
159
|
+
outlook_arrow_size = (play_arrow_size * 2.6).round
|
160
|
+
outlook_arrow_width = (play_arrow_size * 1.0666).round
|
161
|
+
outlook_arrow_height = (play_arrow_size * 0.5333).round
|
162
|
+
outlook_arrow_left = width / 2 - play_arrow_size / 2
|
163
|
+
outlook_arrow_top = height / 2 - play_arrow_size / 2
|
164
|
+
outlook_border_left = width / 2 - outlook_arrow_size / 2
|
165
|
+
outlook_border_top = height / 2 - outlook_arrow_size / 2
|
166
|
+
|
167
|
+
# Use the link central processing routine to ensure a viable link has
|
168
|
+
# been provided and tag/track it from Outlook.
|
169
|
+
outlook_id, outlook_href, target_blank = Link.process(id, href, false, ctx)
|
170
|
+
|
171
|
+
html << %Q(<v:group xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" coordsize="#{width},#{height}" coordorigin="0,0" href="#{outlook_href}" style="width:#{width}px;height:#{height}px;">)
|
172
|
+
html << %Q(<v:rect fill="t" stroked="f" style="position:absolute;width:#{width};height:#{height};"><v:fill src="#{outlook_src}" type="frame"/></v:rect>)
|
173
|
+
html << %Q(<v:oval fill="t" strokecolor="white" strokeweight="4px" style="position:absolute;left:#{outlook_border_left};top:#{outlook_border_top};width:#{outlook_arrow_size};height:#{outlook_arrow_size}"><v:fill color="black" opacity="30%"/></v:oval>)
|
174
|
+
html << %Q(<v:shape coordsize="#{play_border_left},#{outlook_arrow_width}" path="m,l,#{outlook_arrow_width},#{play_border_left},#{outlook_arrow_height},xe" fillcolor="white" stroked="f" style="position:absolute;left:#{outlook_arrow_left};top:#{outlook_arrow_top};width:#{play_arrow_size};height:#{play_arrow_size};"/>)
|
175
|
+
html << '</v:group>'
|
176
|
+
|
177
|
+
# Notify the context that VML was used in this version.
|
178
|
+
ctx.vml_used!
|
179
|
+
|
180
|
+
else
|
181
|
+
|
182
|
+
# This is the only version that can support alt text.
|
183
|
+
alt = opt[:alt] || 'Click to play'
|
184
|
+
|
185
|
+
html << Element.new('a', { :id => id, :href => quote(href) }).to_helper +
|
186
|
+
Element.new('img', { :src => quote(outlook_src), :height => height, :width => width, :alt => quote(alt) }).to_helper +
|
187
|
+
'{/a}'
|
188
|
+
|
189
|
+
end
|
190
|
+
html << '{/outlook-only}'
|
174
191
|
|
175
192
|
# Will hold any CSS styles, if there are some necessary
|
176
193
|
# to inject into the email.
|
data/lib/inkcite/version.rb
CHANGED
data/lib/inkcite/view.rb
CHANGED
@@ -420,9 +420,7 @@ module Inkcite
|
|
420
420
|
|
421
421
|
# Enable responsive media queries on Windows phones courtesy of @jamesmacwhite
|
422
422
|
# https://blog.jmwhite.co.uk/2014/03/01/windows-phone-does-support-css3-media-queries-in-html-email/
|
423
|
-
html << '
|
424
|
-
html << '<meta http-equiv="X-UA-Compatible" content="IE=edge" />'
|
425
|
-
html << '<!--<![endif]-->'
|
423
|
+
html << Renderer.render('{not-outlook}<meta http-equiv="X-UA-Compatible" content="IE=edge" />{/not-outlook}', self)
|
426
424
|
|
427
425
|
# Some native Android clients display the title before the preheader so
|
428
426
|
# don't include it in non-development or email rendering per @moonstrips
|
@@ -847,10 +845,8 @@ module Inkcite
|
|
847
845
|
html.join(NEW_LINE)
|
848
846
|
end
|
849
847
|
|
850
|
-
def load_helper_file
|
848
|
+
def load_helper_file file, into, abort_on_fail=true
|
851
849
|
|
852
|
-
path = @email.path
|
853
|
-
file = File.join(path, filename)
|
854
850
|
unless File.exist?(file)
|
855
851
|
error("Unable to load helper file", :file => file) if abort_on_fail
|
856
852
|
return
|
@@ -904,18 +900,24 @@ module Inkcite
|
|
904
900
|
:n => NEW_LINE
|
905
901
|
}
|
906
902
|
|
903
|
+
# Get the project path from which most helpers will be loaded.
|
904
|
+
path = @email.path
|
905
|
+
|
906
|
+
# First load the built-in helpers.
|
907
|
+
load_helper_file(File.join(Inkcite.asset_path, 'builtin-helpers.tsv'), _helpers, false)
|
908
|
+
|
907
909
|
# Check to see if the config.yml includes a "helpers:" array which allows
|
908
910
|
# additional out-of-project, shared helper files to be loaded.
|
909
911
|
included_helpers = [*@email.config[:helpers]]
|
910
|
-
included_helpers.each { |file| load_helper_file(file, _helpers) }
|
912
|
+
included_helpers.each { |file| load_helper_file(File.join(path, file), _helpers) }
|
911
913
|
|
912
914
|
# Load the project's properties, which may include references to additional
|
913
915
|
# properties in other directories.
|
914
|
-
load_helper_file 'helpers.tsv', _helpers
|
916
|
+
load_helper_file File.join(path, 'helpers.tsv'), _helpers
|
915
917
|
|
916
918
|
# Look for a version-specific override allowing restyling of an email based
|
917
919
|
# on its version - e.g. difference colors in the "no orders for 30 days" email.
|
918
|
-
load_helper_file "helpers-#{@version}.tsv", _helpers, false
|
920
|
+
load_helper_file File.join(path, "helpers-#{@version}.tsv"), _helpers, false
|
919
921
|
|
920
922
|
# As a convenience pre-populate the month name of the email.
|
921
923
|
mm = _helpers[:mm].to_i
|
@@ -5,17 +5,17 @@ describe Inkcite::Renderer::MobileOnly do
|
|
5
5
|
end
|
6
6
|
|
7
7
|
it 'styles a div to show content only on mobile' do
|
8
|
-
Inkcite::Renderer.render('{mobile-only}I will only appear on mobile{/mobile-only}', @view).must_equal('<!--[if !mso 9]
|
8
|
+
Inkcite::Renderer.render('{mobile-only}I will only appear on mobile{/mobile-only}', @view).must_equal('<!--[if !mso 9]><!-- --><div class="show" style="display:none;max-height:0;overflow:hidden">I will only appear on mobile</div><!--<![endif]-->')
|
9
9
|
@view.media_query.find_by_klass('show').declarations.must_match('display: block !important; max-height: none !important;')
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'supports inline as a boolean attribute' do
|
13
|
-
Inkcite::Renderer.render('800-555-1212{mobile-only inline} »{/mobile-only}', @view).must_equal('800-555-1212<!--[if !mso 9]
|
13
|
+
Inkcite::Renderer.render('800-555-1212{mobile-only inline} »{/mobile-only}', @view).must_equal('800-555-1212<!--[if !mso 9]><!-- --><div class="show-inline" style="display:none;max-height:0;overflow:hidden"> »</div><!--<![endif]-->')
|
14
14
|
@view.media_query.find_by_klass('show-inline').declarations.must_match('display: inline !important; max-height: none !important;')
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'does not support fonts or other container attributes' do
|
18
|
-
Inkcite::Renderer.render('{mobile-only font=large}Fonts not supported{/mobile-only}', @view).must_equal('<!--[if !mso 9]
|
18
|
+
Inkcite::Renderer.render('{mobile-only font=large}Fonts not supported{/mobile-only}', @view).must_equal('<!--[if !mso 9]><!-- --><div class="show" style="display:none;max-height:0;overflow:hidden">Fonts not supported</div><!--<![endif]-->')
|
19
19
|
end
|
20
20
|
|
21
21
|
end
|
@@ -5,7 +5,7 @@ describe Inkcite::Renderer::VideoPreview do
|
|
5
5
|
end
|
6
6
|
|
7
7
|
it 'renders an animated video preview' do
|
8
|
-
Inkcite::Renderer.render('{video-preview id="ripcurl" href="https://www.campaignmonitor.com/customers/ripcurl" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame%1.jpg" width=600 height=337 frames=3 bgcolor="#5b5f66" gradient="#1d1f21"}', @view).must_equal(%Q(<!--[if !
|
8
|
+
Inkcite::Renderer.render('{video-preview id="ripcurl" href="https://www.campaignmonitor.com/customers/ripcurl" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame%1.jpg" width=600 height=337 frames=3 bgcolor="#5b5f66" gradient="#1d1f21"}', @view).must_equal(%Q(<!--[if !mso]><!-- -->\n<a class="video" href="https://www.campaignmonitor.com/customers/ripcurl" style="background-color:#5b5f66;background-image:radial-gradient(circle at center, #5b5f66, #1d1f21);color:#0099cc;display:block;text-decoration:none" target=_blank>\n<table border=0 cellpadding=0 cellspacing=0 style="-webkit-animation:video1-frames 15s ease infinite;animation:video1-frames 15s ease infinite;background:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg) 0% 0% / cover no-repeat" width=100%><tr style="transition:all .5s cubic-bezier(0.075, 0.82, 0.165, 1)">\n<td width=25%><img alt="" border=0 src=images/vp-150x337.png style="display:block;height:auto;opacity:0;visibility:hidden" width=100%></td>\n<td align=center valign=middle width=50%>\n<div class="play-button" style="background-image: linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.1)); border: 4px solid white; border-radius: 50%; box-shadow: 0 1px 2px rgba(0,0,0,0.3), inset 0 1px 2px rgba(0,0,0,0.3); height: 34px; margin: 0 auto; padding: 18px 16px 18px 24px; transition: transform .5s cubic-bezier(0.075, 0.82, 0.165, 1); width: 34px;">\n<div style="border-color: transparent transparent transparent white; border-style: solid; border-width: 17px 0 17px 30px; display: block; font-size: 0; height: 0; Margin: 0 auto; width: 0;"> </div>\n</div>\n</td>\n<td width=25%> </td>\n</tr></table>\n</a>\n<div style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg),url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame2.jpg),url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame3.jpg);display:none"></div>\n<!--<![endif]-->\n<!--[if mso]>\n<v:group xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" coordsize="600,337" coordorigin="0,0" href="https://www.campaignmonitor.com/customers/ripcurl" style="width:600px;height:337px;">\n<v:rect fill="t" stroked="f" style="position:absolute;width:600;height:337;"><v:fill src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg" type="frame"/></v:rect>\n<v:oval fill="t" strokecolor="white" strokeweight="4px" style="position:absolute;left:261;top:129;width:78;height:78"><v:fill color="black" opacity="30%"/></v:oval>\n<v:shape coordsize="24,32" path="m,l,32,24,16,xe" fillcolor="white" stroked="f" style="position:absolute;left:285;top:153;width:30;height:30;"/>\n</v:group>\n<![endif]-->))
|
9
9
|
@view.styles.first.must_equal(%Q(.video:hover .play-button {\n transform: scale(1.1);\n}\n.video:hover tr {\n background-color: rgba(255, 255, 255, .2);\n}\n@keyframes video1-frames {\n 0% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg) }\n 22% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg) }\n 33% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame2.jpg) }\n 55% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame2.jpg) }\n 66% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame3.jpg) }\n 88% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame3.jpg) }\n 100% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg) }\n}\n@-webkit-keyframes video1-frames {\n 0% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg) }\n 22% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg) }\n 33% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame2.jpg) }\n 55% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame2.jpg) }\n 66% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame3.jpg) }\n 88% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame3.jpg) }\n 100% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg) }\n}\n))
|
10
10
|
|
11
11
|
# Verify that the transparent spacer image was created and then
|
@@ -16,4 +16,15 @@ describe Inkcite::Renderer::VideoPreview do
|
|
16
16
|
|
17
17
|
end
|
18
18
|
|
19
|
+
it 'supports the outlook-src attribute' do
|
20
|
+
Inkcite::Renderer.render('{video-preview id="ripcurl" href="https://www.campaignmonitor.com/customers/ripcurl" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame%1.jpg" outlook-src="outlook-anim.gif" width=600 height=337 frames=3 bgcolor="#5b5f66" gradient="#1d1f21"}', @view).must_equal(%Q(<!--[if !mso]><!-- -->\n<a class="video" href="https://www.campaignmonitor.com/customers/ripcurl" style="background-color:#5b5f66;background-image:radial-gradient(circle at center, #5b5f66, #1d1f21);color:#0099cc;display:block;text-decoration:none" target=_blank>\n<table border=0 cellpadding=0 cellspacing=0 style="-webkit-animation:video1-frames 15s ease infinite;animation:video1-frames 15s ease infinite;background:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg) 0% 0% / cover no-repeat" width=100%><tr style="transition:all .5s cubic-bezier(0.075, 0.82, 0.165, 1)">\n<td width=25%><img alt="" border=0 src=images/vp-150x337.png style="display:block;height:auto;opacity:0;visibility:hidden" width=100%></td>\n<td align=center valign=middle width=50%>\n<div class="play-button" style="background-image: linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.1)); border: 4px solid white; border-radius: 50%; box-shadow: 0 1px 2px rgba(0,0,0,0.3), inset 0 1px 2px rgba(0,0,0,0.3); height: 34px; margin: 0 auto; padding: 18px 16px 18px 24px; transition: transform .5s cubic-bezier(0.075, 0.82, 0.165, 1); width: 34px;">\n<div style="border-color: transparent transparent transparent white; border-style: solid; border-width: 17px 0 17px 30px; display: block; font-size: 0; height: 0; Margin: 0 auto; width: 0;"> </div>\n</div>\n</td>\n<td width=25%> </td>\n</tr></table>\n</a>\n<div style="background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg),url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame2.jpg),url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame3.jpg);display:none"></div>\n<!--<![endif]-->\n<!--[if mso]>\n<v:group xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" coordsize="600,337" coordorigin="0,0" href="https://www.campaignmonitor.com/customers/ripcurl" style="width:600px;height:337px;">\n<v:rect fill="t" stroked="f" style="position:absolute;width:600;height:337;"><v:fill src="images/outlook-anim.gif" type="frame"/></v:rect>\n<v:oval fill="t" strokecolor="white" strokeweight="4px" style="position:absolute;left:261;top:129;width:78;height:78"><v:fill color="black" opacity="30%"/></v:oval>\n<v:shape coordsize="24,32" path="m,l,32,24,16,xe" fillcolor="white" stroked="f" style="position:absolute;left:285;top:153;width:30;height:30;"/>\n</v:group>\n<![endif]-->))
|
21
|
+
|
22
|
+
# Verify that the transparent spacer image was created and then
|
23
|
+
# clean it up.
|
24
|
+
spacer_image = @view.email.image_path('vp-150x337.png')
|
25
|
+
File.exist?(spacer_image).must_equal(true)
|
26
|
+
File.delete(spacer_image)
|
27
|
+
|
28
|
+
end
|
29
|
+
|
19
30
|
end
|
data/test/view_spec.rb
CHANGED
@@ -25,4 +25,16 @@ describe Inkcite::View do
|
|
25
25
|
Inkcite::Renderer.render('{project}', @view).must_equal('project')
|
26
26
|
end
|
27
27
|
|
28
|
+
it 'can produce Outlook-only code' do
|
29
|
+
Inkcite::Renderer.render('{outlook-only}MSO 07-13{/outlook-only}', @view).must_equal('<!--[if mso]>MSO 07-13<![endif]-->')
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'can produce code only visible in VML-aware clients' do
|
33
|
+
Inkcite::Renderer.render('{vml-only}VML-aware clients only{/vml-only}', @view).must_equal('<!--[if vml]>VML-aware clients only<![endif]-->')
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'can exclude Outlook' do
|
37
|
+
Inkcite::Renderer.render('{not-vml}All except VML-aware clients{/not-vml}', @view).must_equal('<!--[if !vml]><!-- -->All except VML-aware clients<!--<![endif]-->')
|
38
|
+
end
|
39
|
+
|
28
40
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inkcite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.12.
|
4
|
+
version: 1.12.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeffrey D. Hoffman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -345,6 +345,7 @@ files:
|
|
345
345
|
- README.md
|
346
346
|
- Rakefile
|
347
347
|
- assets/blueprint.png
|
348
|
+
- assets/builtin-helpers.tsv
|
348
349
|
- assets/example/helpers.tsv
|
349
350
|
- assets/example/source.html
|
350
351
|
- assets/example/source.txt
|