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