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.
@@ -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