inkcite 1.12.1 → 1.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/inkcite/animation.rb +96 -74
- data/lib/inkcite/cli/base.rb +6 -0
- data/lib/inkcite/cli/preview.rb +1 -1
- data/lib/inkcite/cli/test.rb +3 -3
- data/lib/inkcite/renderer.rb +7 -3
- data/lib/inkcite/renderer/background.rb +153 -0
- data/lib/inkcite/renderer/base.rb +58 -29
- data/lib/inkcite/renderer/container_base.rb +11 -4
- data/lib/inkcite/renderer/div.rb +1 -2
- data/lib/inkcite/renderer/element.rb +6 -7
- data/lib/inkcite/renderer/responsive.rb +124 -37
- data/lib/inkcite/renderer/snow.rb +53 -248
- data/lib/inkcite/renderer/sparkle.rb +77 -0
- data/lib/inkcite/renderer/special_effect.rb +429 -0
- data/lib/inkcite/renderer/style.rb +81 -0
- data/lib/inkcite/renderer/table_base.rb +4 -12
- data/lib/inkcite/renderer/td.rb +6 -24
- data/lib/inkcite/renderer/video_preview.rb +17 -7
- data/lib/inkcite/version.rb +1 -1
- data/lib/inkcite/view.rb +53 -18
- data/lib/inkcite/view/media_query.rb +1 -1
- data/test/animation_spec.rb +14 -10
- data/test/renderer/background_spec.rb +59 -0
- data/test/renderer/div_spec.rb +11 -1
- data/test/renderer/image_spec.rb +1 -1
- data/test/renderer/mobile_image_spec.rb +3 -3
- data/test/renderer/mobile_style_spec.rb +1 -1
- data/test/renderer/span_spec.rb +1 -1
- data/test/renderer/table_spec.rb +22 -7
- data/test/renderer/td_spec.rb +29 -8
- data/test/renderer/video_preview_spec.rb +3 -3
- metadata +8 -5
- data/lib/inkcite/renderer/outlook_background.rb +0 -96
- data/test/renderer/outlook_background_spec.rb +0 -61
data/test/renderer/div_spec.rb
CHANGED
@@ -82,7 +82,7 @@ describe Inkcite::Renderer::Div do
|
|
82
82
|
|
83
83
|
it 'can have a custom line height on mobile' do
|
84
84
|
Inkcite::Renderer.render('{div line-height=15 mobile-line-height=20}{/div}', @view).must_equal('<div class="m1" style="line-height:15px"></div>')
|
85
|
-
@view.media_query.find_by_klass('m1').to_css.must_equal('div
|
85
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('div.m1 { line-height:20px !important }')
|
86
86
|
end
|
87
87
|
|
88
88
|
it 'can have a custom font color on mobile' do
|
@@ -107,4 +107,14 @@ describe Inkcite::Renderer::Div do
|
|
107
107
|
Inkcite::Renderer.render('{div bggradient="radial-gradient(circle at center, #5b5f66, #1d1f21)"}{/div}', @view).must_equal('<div style="background-image:radial-gradient(circle at center, #5b5f66, #1d1f21)"></div>')
|
108
108
|
end
|
109
109
|
|
110
|
+
it 'supports a custom width on mobile' do
|
111
|
+
Inkcite::Renderer.render('{div mobile-width=15}{/div}', @view).must_equal('<div class="m1"></div>')
|
112
|
+
@view.media_query.find_by_klass('m1').declarations.must_match('width:15px')
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'supports a custom override width on mobile' do
|
116
|
+
Inkcite::Renderer.render('{div width=45 mobile-width=78}{/div}', @view).must_equal('<div class="m1" style="width:45px"></div>')
|
117
|
+
@view.media_query.find_by_klass('m1').declarations.must_match('width:78px !important')
|
118
|
+
end
|
119
|
+
|
110
120
|
end
|
data/test/renderer/image_spec.rb
CHANGED
@@ -83,7 +83,7 @@ describe Inkcite::Renderer::Image do
|
|
83
83
|
|
84
84
|
it 'can substitute a different image on mobile' do
|
85
85
|
Inkcite::Renderer.render('{img src=inkcite.jpg mobile-src=inkcite-mobile.jpg height=75 width=125}', @view).must_equal('<img border=0 class="i01" height=75 src="images/inkcite.jpg" style="display:block" width=125>')
|
86
|
-
@view.media_query.find_by_klass('i01').to_css.must_equal('img
|
86
|
+
@view.media_query.find_by_klass('i01').to_css.must_equal('img.i01 { content: url("images/inkcite-mobile.jpg") !important; }')
|
87
87
|
end
|
88
88
|
|
89
89
|
it 'supports fluid-hybrid desktop and style' do
|
@@ -6,14 +6,14 @@ describe Inkcite::Renderer::MobileImage do
|
|
6
6
|
|
7
7
|
it 'styles a span to show an image only on mobile' do
|
8
8
|
Inkcite::Renderer.render('{mobile-img src=inkcite-mobile.jpg height=100 width=300}', @view).must_equal('<span class="i01 img"></span>')
|
9
|
-
@view.media_query.find_by_klass('i01').to_css.must_equal('span
|
10
|
-
@view.media_query.find_by_klass('img').to_css.must_equal('span
|
9
|
+
@view.media_query.find_by_klass('i01').to_css.must_equal('span.i01 { background-image:url("images/inkcite-mobile.jpg");height:100px;width:300px }')
|
10
|
+
@view.media_query.find_by_klass('img').to_css.must_equal('span.img { display: block; background-position: center; background-size: cover; }')
|
11
11
|
end
|
12
12
|
|
13
13
|
it 'substitutes a placeholder for a missing image of sufficient size' do
|
14
14
|
@view.config[Inkcite::Email::IMAGE_PLACEHOLDERS] = true
|
15
15
|
Inkcite::Renderer.render('{mobile-img src=inkcite-mobile.jpg height=100 width=300}', @view).must_equal('<span class="i01 img"></span>')
|
16
|
-
@view.media_query.find_by_klass('i01').to_css.must_equal('span
|
16
|
+
@view.media_query.find_by_klass('i01').to_css.must_equal('span.i01 { background-image:url("http://placeholdit.imgix.net/~text?fm=jpg&h=100&txt=inkcite-mobile.jpg%0A%28300%C3%97100%29&txtsize=18&txttrack=0&w=300");height:100px;width:300px }')
|
17
17
|
end
|
18
18
|
|
19
19
|
end
|
@@ -22,7 +22,7 @@ describe Inkcite::Renderer::MobileStyle do
|
|
22
22
|
|
23
23
|
it 'adds an inactive responsive style to the context' do
|
24
24
|
Inkcite::Renderer.render('{mobile-style name="outlined" style="border: 1px solid #f00"}', @view).must_equal('')
|
25
|
-
@view.media_query.find_by_klass('outlined').to_css.must_equal('
|
25
|
+
@view.media_query.find_by_klass('outlined').to_css.must_equal('.outlined { border: 1px solid #f00 }')
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'can be applied to a responsive element' do
|
data/test/renderer/span_spec.rb
CHANGED
@@ -78,7 +78,7 @@ describe Inkcite::Renderer::Span do
|
|
78
78
|
|
79
79
|
it 'can have a custom line height on mobile' do
|
80
80
|
Inkcite::Renderer.render('{span line-height=15 mobile-line-height=20}{/span}', @view).must_equal('<span class="m1" style="line-height:15px"></span>')
|
81
|
-
@view.media_query.find_by_klass('m1').to_css.must_equal('span
|
81
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('span.m1 { line-height:20px !important }')
|
82
82
|
end
|
83
83
|
|
84
84
|
it 'can inherit a custom font size on mobile from the context' do
|
data/test/renderer/table_spec.rb
CHANGED
@@ -9,22 +9,37 @@ describe Inkcite::Renderer::Table do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'supports custom margins in px' do
|
12
|
-
Inkcite::Renderer.render('{table margin-top=15}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="
|
13
|
-
Inkcite::Renderer.render('{table margin-left=16}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="
|
14
|
-
Inkcite::Renderer.render('{table margin-bottom=17}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="
|
15
|
-
Inkcite::Renderer.render('{table margin-right=18}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="
|
12
|
+
Inkcite::Renderer.render('{table margin-top=15}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="Margin-top:15px"><tr>')
|
13
|
+
Inkcite::Renderer.render('{table margin-left=16}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="Margin-left:16px"><tr>')
|
14
|
+
Inkcite::Renderer.render('{table margin-bottom=17}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="Margin-bottom:17px"><tr>')
|
15
|
+
Inkcite::Renderer.render('{table margin-right=18}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="Margin-right:18px"><tr>')
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'supports multiple custom margins in px' do
|
19
|
-
Inkcite::Renderer.render('{table margin-top=15 margin-left=6}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="
|
19
|
+
Inkcite::Renderer.render('{table margin-top=15 margin-left=6}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="Margin-left:6px;Margin-top:15px"><tr>')
|
20
20
|
end
|
21
21
|
|
22
22
|
it 'supports a single all margin attribute' do
|
23
|
-
Inkcite::Renderer.render('{table margin=15}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="
|
23
|
+
Inkcite::Renderer.render('{table margin=15}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="Margin:15px"><tr>')
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'supports unified margins with directional override' do
|
27
|
-
Inkcite::Renderer.render('{table margin=15 margin-left=8}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="
|
27
|
+
Inkcite::Renderer.render('{table margin=15 margin-left=8}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="Margin:15px;Margin-left:8px"><tr>')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'supports custom margins on mobile' do
|
31
|
+
Inkcite::Renderer.render('{table mobile-margin=15}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 class="m1"><tr>')
|
32
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('table.m1 { margin:15px }')
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'supports custom margin override on mobile' do
|
36
|
+
Inkcite::Renderer.render('{table margin="12px 4px 0" mobile-margin=15}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 class="m1" style="Margin:12px 4px 0"><tr>')
|
37
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('table.m1 { margin:15px !important }')
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'supports margin shortcuts on mobile' do
|
41
|
+
Inkcite::Renderer.render('{table mobile-margin="15px 8px"}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 class="m1"><tr>')
|
42
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('table.m1 { margin:15px 8px }')
|
28
43
|
end
|
29
44
|
|
30
45
|
it 'supports fluid-hybrid desktop and style' do
|
data/test/renderer/td_spec.rb
CHANGED
@@ -12,6 +12,22 @@ describe Inkcite::Renderer::Td do
|
|
12
12
|
Inkcite::Renderer.render('{table padding=15}{td}', @view).must_equal('<table border=0 cellpadding=15 cellspacing=0><tr><td style="padding:15px">')
|
13
13
|
end
|
14
14
|
|
15
|
+
it 'supports mobile padding from the parent table' do
|
16
|
+
Inkcite::Renderer.render('{table mobile-padding=15}{td}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0><tr><td class="m1">')
|
17
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('td.m1 { padding:15px }')
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'reuses a style that matches mobile padding' do
|
21
|
+
Inkcite::Renderer.render('{table mobile-padding=15}{td}{table mobile-padding=15}{td}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0><tr><td class="m1"><table border=0 cellpadding=0 cellspacing=0><tr><td class="m1">')
|
22
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('td.m1 { padding:15px }')
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'supports override mobile padding from the parent table' do
|
27
|
+
Inkcite::Renderer.render('{table padding=30 mobile-padding=15}{td}', @view).must_equal('<table border=0 cellpadding=30 cellspacing=0><tr><td class="m1" style="padding:30px">')
|
28
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('td.m1 { padding:15px !important }')
|
29
|
+
end
|
30
|
+
|
15
31
|
it 'does not accept padding as an attribute' do
|
16
32
|
Inkcite::Renderer.render('{td padding=15}', @view).must_equal('<td>')
|
17
33
|
end
|
@@ -77,8 +93,13 @@ describe Inkcite::Renderer::Td do
|
|
77
93
|
end
|
78
94
|
|
79
95
|
it 'can have a mobile behavior and a custom mobile style simultaneously' do
|
80
|
-
Inkcite::Renderer.render('{td mobile="drop" mobile-
|
81
|
-
@view.media_query.find_by_klass('m1').to_css.must_equal('td
|
96
|
+
Inkcite::Renderer.render('{td mobile="drop" mobile-border="1px solid #f00"}', @view).must_equal('<td class="drop m1">')
|
97
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('td.m1 { border:1px solid #f00 }')
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'can have a mobile border that overrides a custom border' do
|
101
|
+
Inkcite::Renderer.render('{td mobile="drop" border="2px dashed #0f0" mobile-border="1px solid #f00"}', @view).must_equal('<td class="drop m1" style="border:2px dashed #0f0">')
|
102
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('td.m1 { border:1px solid #f00 !important }')
|
82
103
|
end
|
83
104
|
|
84
105
|
it 'can have a background color' do
|
@@ -87,12 +108,12 @@ describe Inkcite::Renderer::Td do
|
|
87
108
|
|
88
109
|
it 'can have a custom background color on mobile' do
|
89
110
|
Inkcite::Renderer.render('{td mobile-bgcolor=#f09}', @view).must_equal('<td class="m1">')
|
90
|
-
@view.media_query.find_by_klass('m1').to_css.must_equal('td
|
111
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('td.m1 { background:#ff0099 }')
|
91
112
|
end
|
92
113
|
|
93
114
|
it 'can override background color on mobile' do
|
94
115
|
Inkcite::Renderer.render('{td bgcolor=#f00 mobile-bgcolor=#00f}', @view).must_equal('<td bgcolor=#ff0000 class="m1">')
|
95
|
-
@view.media_query.find_by_klass('m1').to_css.must_equal('td
|
116
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('td.m1 { background:#0000ff }')
|
96
117
|
end
|
97
118
|
|
98
119
|
it 'can have a background image' do
|
@@ -105,22 +126,22 @@ describe Inkcite::Renderer::Td do
|
|
105
126
|
|
106
127
|
it 'can have a background image on mobile' do
|
107
128
|
Inkcite::Renderer.render('{td mobile-background-image=wall.jpg mobile-background-position=right mobile-background-repeat=repeat-y}', @view).must_equal('<td class="m1">')
|
108
|
-
@view.media_query.find_by_klass('m1').to_css.must_equal('td
|
129
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('td.m1 { background:url(images/wall.jpg) right repeat-y }')
|
109
130
|
end
|
110
131
|
|
111
132
|
it 'can override background image on mobile' do
|
112
133
|
Inkcite::Renderer.render('{td background=floor.jpg mobile-background-image=sky.jpg }', @view).must_equal('<td class="m1" style="background:url(images/floor.jpg)">')
|
113
|
-
@view.media_query.find_by_klass('m1').to_css.must_equal('td
|
134
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('td.m1 { background:url(images/sky.jpg) !important }')
|
114
135
|
end
|
115
136
|
|
116
137
|
it 'can override background position on mobile' do
|
117
138
|
Inkcite::Renderer.render('{td background=floor.jpg background-position=bottom mobile-background-position=top}', @view).must_equal('<td class="m1" style="background:url(images/floor.jpg) bottom no-repeat">')
|
118
|
-
@view.media_query.find_by_klass('m1').to_css.must_equal('td
|
139
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('td.m1 { background:url(images/floor.jpg) top no-repeat !important }')
|
119
140
|
end
|
120
141
|
|
121
142
|
it 'can disable background image on mobile' do
|
122
143
|
Inkcite::Renderer.render('{td background=floor.jpg mobile-background-image=none}', @view).must_equal('<td class="m1" style="background:url(images/floor.jpg)">')
|
123
|
-
@view.media_query.find_by_klass('m1').to_css.must_equal('td
|
144
|
+
@view.media_query.find_by_klass('m1').to_css.must_equal('td.m1 { background:none !important }')
|
124
145
|
end
|
125
146
|
|
126
147
|
it 'supports nowrap' do
|
@@ -5,8 +5,8 @@ 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 !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:
|
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 {\
|
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:15s ease infinite video1-frames;animation:15s ease infinite video1-frames;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
|
+
@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 {\n0% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg) }\n22% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg) }\n33% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame2.jpg) }\n55% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame2.jpg) }\n66% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame3.jpg) }\n88% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame3.jpg) }\n100% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg) }\n}\n@-webkit-keyframes video1-frames {\n0% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg) }\n22% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame1.jpg) }\n33% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame2.jpg) }\n55% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame2.jpg) }\n66% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame3.jpg) }\n88% { background-image:url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/103009/frame3.jpg) }\n100% { 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
|
12
12
|
# clean it up.
|
@@ -17,7 +17,7 @@ describe Inkcite::Renderer::VideoPreview do
|
|
17
17
|
end
|
18
18
|
|
19
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:
|
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:15s ease infinite video1-frames;animation:15s ease infinite video1-frames;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
21
|
|
22
22
|
# Verify that the transparent spacer image was created and then
|
23
23
|
# clean it up.
|
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.
|
4
|
+
version: 1.13.0
|
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: 2017-01-
|
11
|
+
date: 2017-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -375,6 +375,7 @@ files:
|
|
375
375
|
- lib/inkcite/minifier.rb
|
376
376
|
- lib/inkcite/parser.rb
|
377
377
|
- lib/inkcite/renderer.rb
|
378
|
+
- lib/inkcite/renderer/background.rb
|
378
379
|
- lib/inkcite/renderer/base.rb
|
379
380
|
- lib/inkcite/renderer/button.rb
|
380
381
|
- lib/inkcite/renderer/container_base.rb
|
@@ -394,7 +395,6 @@ files:
|
|
394
395
|
- lib/inkcite/renderer/mobile_only.rb
|
395
396
|
- lib/inkcite/renderer/mobile_style.rb
|
396
397
|
- lib/inkcite/renderer/mobile_toggle.rb
|
397
|
-
- lib/inkcite/renderer/outlook_background.rb
|
398
398
|
- lib/inkcite/renderer/partial.rb
|
399
399
|
- lib/inkcite/renderer/preheader.rb
|
400
400
|
- lib/inkcite/renderer/property.rb
|
@@ -403,6 +403,9 @@ files:
|
|
403
403
|
- lib/inkcite/renderer/snow.rb
|
404
404
|
- lib/inkcite/renderer/social.rb
|
405
405
|
- lib/inkcite/renderer/span.rb
|
406
|
+
- lib/inkcite/renderer/sparkle.rb
|
407
|
+
- lib/inkcite/renderer/special_effect.rb
|
408
|
+
- lib/inkcite/renderer/style.rb
|
406
409
|
- lib/inkcite/renderer/table.rb
|
407
410
|
- lib/inkcite/renderer/table_base.rb
|
408
411
|
- lib/inkcite/renderer/td.rb
|
@@ -423,6 +426,7 @@ files:
|
|
423
426
|
- test/project/images/inkcite.jpg
|
424
427
|
- test/project/source.html
|
425
428
|
- test/project/source.txt
|
429
|
+
- test/renderer/background_spec.rb
|
426
430
|
- test/renderer/button_spec.rb
|
427
431
|
- test/renderer/div_spec.rb
|
428
432
|
- test/renderer/element_spec.rb
|
@@ -433,7 +437,6 @@ files:
|
|
433
437
|
- test/renderer/mobile_image_spec.rb
|
434
438
|
- test/renderer/mobile_only_spec.rb
|
435
439
|
- test/renderer/mobile_style_spec.rb
|
436
|
-
- test/renderer/outlook_background_spec.rb
|
437
440
|
- test/renderer/redacted_spec.rb
|
438
441
|
- test/renderer/social_spec.rb
|
439
442
|
- test/renderer/span_spec.rb
|
@@ -477,6 +480,7 @@ test_files:
|
|
477
480
|
- test/project/images/inkcite.jpg
|
478
481
|
- test/project/source.html
|
479
482
|
- test/project/source.txt
|
483
|
+
- test/renderer/background_spec.rb
|
480
484
|
- test/renderer/button_spec.rb
|
481
485
|
- test/renderer/div_spec.rb
|
482
486
|
- test/renderer/element_spec.rb
|
@@ -487,7 +491,6 @@ test_files:
|
|
487
491
|
- test/renderer/mobile_image_spec.rb
|
488
492
|
- test/renderer/mobile_only_spec.rb
|
489
493
|
- test/renderer/mobile_style_spec.rb
|
490
|
-
- test/renderer/outlook_background_spec.rb
|
491
494
|
- test/renderer/redacted_spec.rb
|
492
495
|
- test/renderer/social_spec.rb
|
493
496
|
- test/renderer/span_spec.rb
|
@@ -1,96 +0,0 @@
|
|
1
|
-
module Inkcite
|
2
|
-
module Renderer
|
3
|
-
|
4
|
-
# Outlook background image support courtesy of @stigm via Campaign Monitor's
|
5
|
-
# Bulletproof Background Images: https://backgrounds.cm/
|
6
|
-
#
|
7
|
-
# {outlook-bg src=YJOX1PC.png bgcolor=#7bceeb height=92 width=120}
|
8
|
-
# ...
|
9
|
-
# {/outlook-bg}
|
10
|
-
#
|
11
|
-
class OutlookBackground < ImageBase
|
12
|
-
|
13
|
-
def render tag, opt, ctx
|
14
|
-
|
15
|
-
# Do nothing if vml is disabled globally. Disable by setting
|
16
|
-
# 'vml: false' in config.yml
|
17
|
-
return nil unless ctx.vml_enabled?
|
18
|
-
|
19
|
-
html = '{if test="gte mso 9"}'
|
20
|
-
|
21
|
-
if tag == '/outlook-bg'
|
22
|
-
html << '</div>'
|
23
|
-
html << '</v:textbox>'
|
24
|
-
html << '</v:rect>'
|
25
|
-
|
26
|
-
else
|
27
|
-
|
28
|
-
# Get the fully-qualified URL to the image or placeholder image if it's
|
29
|
-
# missing from the images directory.
|
30
|
-
src = image_url(opt[:src], opt, ctx, false)
|
31
|
-
|
32
|
-
rect = Element.new('v:rect', {
|
33
|
-
:'xmlns:v' => quote('urn:schemas-microsoft-com:vml'),
|
34
|
-
:fill => quote(true),
|
35
|
-
:stroke => quote(false)
|
36
|
-
})
|
37
|
-
|
38
|
-
width = opt[:width]
|
39
|
-
height = opt[:height].to_i
|
40
|
-
|
41
|
-
# When width is omitted, set to 100% or marked as 'fill' then
|
42
|
-
# make the image fill the available space. It will tile.
|
43
|
-
if width.nil? || width == 'fill' || width == '100%' || width.to_i <= 0
|
44
|
-
|
45
|
-
# The number you pass to 'mso-width-percent' is ten times the percentage you'd like.
|
46
|
-
# https://www.emailonacid.com/blog/article/email-development/emailology_vector_markup_language_and_backgrounds
|
47
|
-
rect.style[:'mso-width-percent'] = 1000
|
48
|
-
|
49
|
-
else
|
50
|
-
rect.style[:width] = px(width)
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
# True if the height of the background image will fit to content within the
|
55
|
-
# background element (specified by omitting the 'height' attribute).
|
56
|
-
fit_to_shape = height <= 0
|
57
|
-
rect.style[:height] = px(height) unless fit_to_shape
|
58
|
-
|
59
|
-
fill = Element.new('v:fill', {
|
60
|
-
:type => '"tile"',
|
61
|
-
:src => src,
|
62
|
-
:self_close => true
|
63
|
-
})
|
64
|
-
|
65
|
-
# Check for a background color.
|
66
|
-
bgcolor = opt[:bgcolor]
|
67
|
-
fill[:color] = quote(hex(bgcolor)) unless bgcolor.blank?
|
68
|
-
|
69
|
-
textbox = Element.new('v:textbox', :inset => '"0,0,0,0"')
|
70
|
-
textbox.style[:'mso-fit-shape-to-text'] = 'true' if fit_to_shape
|
71
|
-
|
72
|
-
html << rect.to_s
|
73
|
-
html << fill.to_s
|
74
|
-
html << textbox.to_s
|
75
|
-
|
76
|
-
div = Element.new('div')
|
77
|
-
|
78
|
-
# Font family and other attributes get reset within the v:textbox so allow
|
79
|
-
# the font series of attributes to be applied.
|
80
|
-
mix_font div, opt, ctx
|
81
|
-
|
82
|
-
html << div.to_s
|
83
|
-
|
84
|
-
# Flag the context as having had VML used within it.
|
85
|
-
ctx.vml_used!
|
86
|
-
|
87
|
-
end
|
88
|
-
|
89
|
-
html << '{/if}'
|
90
|
-
|
91
|
-
html
|
92
|
-
end
|
93
|
-
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
describe Inkcite::Renderer::OutlookBackground do
|
2
|
-
|
3
|
-
before do
|
4
|
-
@view = Inkcite::Email.new('test/project/').view(:development, :email)
|
5
|
-
end
|
6
|
-
|
7
|
-
it 'warns when an image is missing' do
|
8
|
-
Inkcite::Renderer.render('{outlook-bg src=missing.jpg}', @view)
|
9
|
-
@view.errors.must_include('Missing image (line 0) [src=missing.jpg]')
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'defaults to filling the available horizontal space' do
|
13
|
-
Inkcite::Renderer.render('{outlook-bg src=https://i.imgur.com/YJOX1PC.png}{/outlook-bg}', @view).must_equal('<!--[if gte mso 9]><v:rect fill="true" stroke="false" style="mso-width-percent:1000" xmlns:v="urn:schemas-microsoft-com:vml"><v:fill src="https://i.imgur.com/YJOX1PC.png" type="tile" /><v:textbox inset="0,0,0,0" style="mso-fit-shape-to-text:true"><div><![endif]--><!--[if gte mso 9]></div></v:textbox></v:rect><![endif]-->')
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'supports 100% width' do
|
17
|
-
Inkcite::Renderer.render('{outlook-bg src=https://i.imgur.com/YJOX1PC.png width=100%}{/outlook-bg}', @view).must_equal('<!--[if gte mso 9]><v:rect fill="true" stroke="false" style="mso-width-percent:1000" xmlns:v="urn:schemas-microsoft-com:vml"><v:fill src="https://i.imgur.com/YJOX1PC.png" type="tile" /><v:textbox inset="0,0,0,0" style="mso-fit-shape-to-text:true"><div><![endif]--><!--[if gte mso 9]></div></v:textbox></v:rect><![endif]-->')
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'supports fill width' do
|
21
|
-
Inkcite::Renderer.render('{outlook-bg src=https://i.imgur.com/YJOX1PC.png width=fill}{/outlook-bg}', @view).must_equal('<!--[if gte mso 9]><v:rect fill="true" stroke="false" style="mso-width-percent:1000" xmlns:v="urn:schemas-microsoft-com:vml"><v:fill src="https://i.imgur.com/YJOX1PC.png" type="tile" /><v:textbox inset="0,0,0,0" style="mso-fit-shape-to-text:true"><div><![endif]--><!--[if gte mso 9]></div></v:textbox></v:rect><![endif]-->')
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'supports an optional width in pixels' do
|
25
|
-
Inkcite::Renderer.render('{outlook-bg src=https://i.imgur.com/YJOX1PC.png width=120}{/outlook-bg}', @view).must_equal('<!--[if gte mso 9]><v:rect fill="true" stroke="false" style="width:120px" xmlns:v="urn:schemas-microsoft-com:vml"><v:fill src="https://i.imgur.com/YJOX1PC.png" type="tile" /><v:textbox inset="0,0,0,0" style="mso-fit-shape-to-text:true"><div><![endif]--><!--[if gte mso 9]></div></v:textbox></v:rect><![endif]-->')
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'supports an optional height in pixels' do
|
29
|
-
Inkcite::Renderer.render('{outlook-bg src=https://i.imgur.com/YJOX1PC.png bgcolor=#7bceeb height=92 width=120}{/outlook-bg}', @view).must_equal('<!--[if gte mso 9]><v:rect fill="true" stroke="false" style="height:92px;width:120px" xmlns:v="urn:schemas-microsoft-com:vml"><v:fill color="#7bceeb" src="https://i.imgur.com/YJOX1PC.png" type="tile" /><v:textbox inset="0,0,0,0"><div><![endif]--><!--[if gte mso 9]></div></v:textbox></v:rect><![endif]-->')
|
30
|
-
end
|
31
|
-
|
32
|
-
|
33
|
-
it 'supports an optional background color' do
|
34
|
-
Inkcite::Renderer.render('{outlook-bg src=https://i.imgur.com/YJOX1PC.png bgcolor=#7bceeb width=120}{/outlook-bg}', @view).must_equal('<!--[if gte mso 9]><v:rect fill="true" stroke="false" style="width:120px" xmlns:v="urn:schemas-microsoft-com:vml"><v:fill color="#7bceeb" src="https://i.imgur.com/YJOX1PC.png" type="tile" /><v:textbox inset="0,0,0,0" style="mso-fit-shape-to-text:true"><div><![endif]--><!--[if gte mso 9]></div></v:textbox></v:rect><![endif]-->')
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'is automatically injected by the td helper' do
|
38
|
-
Inkcite::Renderer.render('{td background=https://i.imgur.com/YJOX1PC.png bgcolor=#7bceeb width=120 outlook-bg}{/td}', @view).must_equal(%Q(<td bgcolor=#7bceeb style="background:#7bceeb url(https://i.imgur.com/YJOX1PC.png)" width=120>\n<!--[if gte mso 9]><v:rect fill="true" stroke="false" style="width:120px" xmlns:v="urn:schemas-microsoft-com:vml"><v:fill color="#7bceeb" src="https://i.imgur.com/YJOX1PC.png" type="tile" /><v:textbox inset="0,0,0,0" style="mso-fit-shape-to-text:true"><div><![endif]--><!--[if gte mso 9]></div></v:textbox></v:rect><![endif]-->\n</td>))
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'defaults to fill when injected by a td helper sans dimensions' do
|
42
|
-
Inkcite::Renderer.render('{td background=https://i.imgur.com/YJOX1PC.png bgcolor=#7bceeb outlook-bg}{/td}', @view).must_equal(%Q(<td bgcolor=#7bceeb style="background:#7bceeb url(https://i.imgur.com/YJOX1PC.png)">\n<!--[if gte mso 9]><v:rect fill="true" stroke="false" style="mso-width-percent:1000" xmlns:v="urn:schemas-microsoft-com:vml"><v:fill color="#7bceeb" src="https://i.imgur.com/YJOX1PC.png" type="tile" /><v:textbox inset="0,0,0,0" style="mso-fit-shape-to-text:true"><div><![endif]--><!--[if gte mso 9]></div></v:textbox></v:rect><![endif]-->\n</td>))
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'inherits height from the parent td if present' do
|
46
|
-
Inkcite::Renderer.render('{td background=https://i.imgur.com/YJOX1PC.png bgcolor=#7bceeb height=92 width=120 outlook-bg}{/td}', @view).must_equal(%Q(<td bgcolor=#7bceeb height=92 style="background:#7bceeb url(https://i.imgur.com/YJOX1PC.png)" width=120>\n<!--[if gte mso 9]><v:rect fill="true" stroke="false" style="height:92px;width:120px" xmlns:v="urn:schemas-microsoft-com:vml"><v:fill color="#7bceeb" src="https://i.imgur.com/YJOX1PC.png" type="tile" /><v:textbox inset="0,0,0,0"><div><![endif]--><!--[if gte mso 9]></div></v:textbox></v:rect><![endif]-->\n</td>))
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'is ignored by the td helper if background is missing' do
|
50
|
-
Inkcite::Renderer.render('{td bgcolor=#7bceeb outlook-bg}{/td}', @view).must_equal(%Q(<td bgcolor=#7bceeb></td>))
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'supports the font attribute' do
|
54
|
-
Inkcite::Renderer.render('{outlook-bg src=https://i.imgur.com/YJOX1PC.png font=large}{/outlook-bg}', @view).must_equal('<!--[if gte mso 9]><v:rect fill="true" stroke="false" style="mso-width-percent:1000" xmlns:v="urn:schemas-microsoft-com:vml"><v:fill src="https://i.imgur.com/YJOX1PC.png" type="tile" /><v:textbox inset="0,0,0,0" style="mso-fit-shape-to-text:true"><div style="color:#ff0000;font-family:serif;font-size:24px;font-weight:bold;line-height:24px"><![endif]--><!--[if gte mso 9]></div></v:textbox></v:rect><![endif]-->')
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'supports font-related attributes' do
|
58
|
-
Inkcite::Renderer.render('{outlook-bg src=https://i.imgur.com/YJOX1PC.png font-size=18 line-height=27}{/outlook-bg}', @view).must_equal('<!--[if gte mso 9]><v:rect fill="true" stroke="false" style="mso-width-percent:1000" xmlns:v="urn:schemas-microsoft-com:vml"><v:fill src="https://i.imgur.com/YJOX1PC.png" type="tile" /><v:textbox inset="0,0,0,0" style="mso-fit-shape-to-text:true"><div style="font-size:18px;line-height:27px"><![endif]--><!--[if gte mso 9]></div></v:textbox></v:rect><![endif]-->')
|
59
|
-
end
|
60
|
-
|
61
|
-
end
|