inkcite 1.12.1 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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[class~="m1"] { line-height:20px !important }')
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
@@ -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[class~="i01"] { content: url("images/inkcite-mobile.jpg") !important; }')
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[class~="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[class~="img"] { display: block; background-position: center; background-size: cover; }')
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[class~="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 }')
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('[class~="outlined"] { border: 1px solid #f00 }')
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
@@ -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[class~="m1"] { line-height:20px !important }')
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
@@ -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="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>')
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="margin-left:6px;margin-top:15px"><tr>')
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="margin-bottom:15px;margin-left:15px;margin-right:15px;margin-top:15px"><tr>')
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="margin-bottom:15px;margin-left:8px;margin-right:15px;margin-top:15px"><tr>')
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
@@ -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-style="border: 1px solid #f00"}', @view).must_equal('<td class="drop m1">')
81
- @view.media_query.find_by_klass('m1').to_css.must_equal('td[class~="m1"] { border: 1px solid #f00 }')
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[class~="m1"] { background:#ff0099 }')
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[class~="m1"] { background:#0000ff !important }')
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[class~="m1"] { background:url(images/wall.jpg) right repeat-y }')
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[class~="m1"] { background:url(images/sky.jpg) !important }')
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[class~="m1"] { background:url(images/floor.jpg) top no-repeat !important }')
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[class~="m1"] { background:none !important }')
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: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;">&nbsp;</div>\n</div>\n</td>\n<td width=25%>&nbsp;</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 {\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))
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;">&nbsp;</div>\n</div>\n</td>\n<td width=25%>&nbsp;</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: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;">&nbsp;</div>\n</div>\n</td>\n<td width=25%>&nbsp;</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]-->))
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;">&nbsp;</div>\n</div>\n</td>\n<td width=25%>&nbsp;</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.12.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-05 00:00:00.000000000 Z
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