inkcite 1.12.0 → 1.12.1
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/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
|