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
@@ -0,0 +1,81 @@
|
|
1
|
+
module Inkcite
|
2
|
+
module Renderer
|
3
|
+
class Style
|
4
|
+
|
5
|
+
def initialize name, ctx, styles={}
|
6
|
+
|
7
|
+
@name = name
|
8
|
+
@ctx = ctx
|
9
|
+
@styles = styles
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
def [] key
|
14
|
+
@styles[key]
|
15
|
+
end
|
16
|
+
|
17
|
+
def []= key, val
|
18
|
+
@styles[key] = val
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_css allowed_prefixes=nil
|
22
|
+
"#{@name} { #{to_inline_css(allowed_prefixes)} }"
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_inline_css allowed_prefixes=nil
|
26
|
+
|
27
|
+
# Inherit the list of allowed prefixes from the context if
|
28
|
+
# none were provided. Otherwise, make sure we're working
|
29
|
+
# with an array.
|
30
|
+
if allowed_prefixes.nil?
|
31
|
+
allowed_prefixes = @ctx.prefixes
|
32
|
+
else
|
33
|
+
allowed_prefixes = [*allowed_prefixes]
|
34
|
+
end
|
35
|
+
|
36
|
+
# This will hold a copy of the key and values including
|
37
|
+
# all keys with prefixes.
|
38
|
+
_styles = {}
|
39
|
+
|
40
|
+
# A reusable array indicating no prefixing is necessary.
|
41
|
+
no_prefixes = ['']
|
42
|
+
|
43
|
+
@styles.each_pair do |key, val|
|
44
|
+
|
45
|
+
# Determine which list of prefixes are needed based on the
|
46
|
+
# original key (e.g. :transform) - or use the list of
|
47
|
+
# non-modifying prefixes.
|
48
|
+
prefixes = if Inkcite::Renderer::Style.needs_prefixing?(key)
|
49
|
+
allowed_prefixes
|
50
|
+
else
|
51
|
+
no_prefixes
|
52
|
+
end
|
53
|
+
|
54
|
+
# Iterate through each prefix and create a hybrid key. Then
|
55
|
+
# add the styles to the temporary list.
|
56
|
+
prefixes.each do |prefix|
|
57
|
+
prefixed_key = "#{prefix}#{key}".to_sym
|
58
|
+
_styles[prefixed_key] = val
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
Renderer.render_styles(_styles)
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_s
|
67
|
+
@name.blank? ? to_inline_css : to_css
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.needs_prefixing? key
|
71
|
+
PREFIXABLE_KEYS.include?(key.to_sym)
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
# Array of CSS attributes that must be prefixed (e.g. transform and animation)
|
77
|
+
PREFIXABLE_KEYS = [:animation, :transform]
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -16,6 +16,7 @@ module Inkcite
|
|
16
16
|
mix_background element, opt, ctx
|
17
17
|
mix_border element, opt, ctx
|
18
18
|
mix_dimensions element, opt, ctx
|
19
|
+
mix_margins element, opt, ctx
|
19
20
|
|
20
21
|
end
|
21
22
|
|
@@ -51,24 +52,15 @@ module Inkcite
|
|
51
52
|
# mobile version inherits from the desktop version.
|
52
53
|
mobile_background = mix_background_shorthand(
|
53
54
|
detect(opt[MOBILE_BACKGROUND_COLOR], opt[MOBILE_BGCOLOR], bgcolor),
|
54
|
-
detect(opt[MOBILE_BACKGROUND_IMAGE], opt[MOBILE_BACKGROUND], bgimage),
|
55
|
+
detect(opt[MOBILE_BACKGROUND_IMAGE], opt[MOBILE_BACKGROUND], opt[MOBILE_SRC], bgimage),
|
55
56
|
detect(opt[MOBILE_BACKGROUND_POSITION], bgposition),
|
56
57
|
detect(opt[MOBILE_BACKGROUND_REPEAT], bgrepeat),
|
57
58
|
detect(opt[MOBILE_BACKGROUND_SIZE], bgsize),
|
58
59
|
ctx
|
59
60
|
)
|
60
61
|
|
61
|
-
|
62
|
-
|
63
|
-
mobile_background << ' !important' unless desktop_background.blank?
|
64
|
-
|
65
|
-
# Add the responsive rule that applies to this element.
|
66
|
-
rule = Rule.new(element.tag, unique_klass(ctx), { :background => mobile_background })
|
67
|
-
|
68
|
-
# Add the rule to the view and the element
|
69
|
-
ctx.media_query << rule
|
70
|
-
element.add_rule rule
|
71
|
-
|
62
|
+
if !mobile_background.blank? && mobile_background != desktop_background
|
63
|
+
element.mobile_style[:background] = mobile_background
|
72
64
|
end
|
73
65
|
|
74
66
|
end
|
data/lib/inkcite/renderer/td.rb
CHANGED
@@ -27,10 +27,6 @@ module Inkcite
|
|
27
27
|
# Retrieve the opts that were used to open this TD.
|
28
28
|
open_opt = tag_stack.pop
|
29
29
|
|
30
|
-
# If the opening tag initiated an automatic outlook background
|
31
|
-
# then we need to inject the close tag here.
|
32
|
-
html << "{/outlook-bg}\n" if outlook_bg?(open_opt)
|
33
|
-
|
34
30
|
# Normal HTML produced by the Helper to close the cell.
|
35
31
|
html << '</td>'
|
36
32
|
|
@@ -76,6 +72,12 @@ module Inkcite
|
|
76
72
|
|
77
73
|
mobile = opt[:mobile]
|
78
74
|
|
75
|
+
# If the table defines mobile-padding, then apply the correct mobile
|
76
|
+
# style to this td - and its !important if there is padding on
|
77
|
+
# the td already.
|
78
|
+
mobile_padding = table_opt[MOBILE_PADDING] || opt[MOBILE_PADDING]
|
79
|
+
td.mobile_style[:padding] = px(mobile_padding) unless mobile_padding.blank? || mobile == HIDE
|
80
|
+
|
79
81
|
# Need to handle Fluid-Drop HTML injection here before the rest of the
|
80
82
|
# TD is formalized. Fluid-Drop removes the width attribute of the cell
|
81
83
|
# as it is wrapped in a 100%-width table.
|
@@ -170,21 +172,6 @@ module Inkcite
|
|
170
172
|
|
171
173
|
html << td.to_s
|
172
174
|
|
173
|
-
# For convenience and to keep code DRY, support the outlook-bg boolean
|
174
|
-
# attribute which causes an {outlook-bg} Helper to be injected automatically
|
175
|
-
# inside of the {td}.
|
176
|
-
if outlook_bg?(opt)
|
177
|
-
|
178
|
-
html << "\n"
|
179
|
-
html << Element.new('outlook-bg', {
|
180
|
-
:bgcolor => detect_bgcolor(opt),
|
181
|
-
:width => opt[:width],
|
182
|
-
:height => opt[:height],
|
183
|
-
:src => opt[:background]
|
184
|
-
}).to_helper
|
185
|
-
|
186
|
-
end
|
187
|
-
|
188
175
|
end
|
189
176
|
|
190
177
|
html
|
@@ -192,11 +179,6 @@ module Inkcite
|
|
192
179
|
|
193
180
|
private
|
194
181
|
|
195
|
-
# Returns true if the conditions are met that enable the
|
196
|
-
# automatic {outlook-bg} helper integration.
|
197
|
-
def outlook_bg? opt
|
198
|
-
opt && opt[OUTLOOK_BG] && !opt[:background].blank?
|
199
|
-
end
|
200
182
|
|
201
183
|
CLOSE_TD = '/td'
|
202
184
|
LEFT = 'left'
|
@@ -94,7 +94,19 @@ module Inkcite
|
|
94
94
|
:width => '100%', :background => first_frame, BACKGROUND_SIZE => 'cover',
|
95
95
|
Table::TR_TRANSITION => %q("all .5s cubic-bezier(0.075, 0.82, 0.165, 1)")
|
96
96
|
})
|
97
|
-
|
97
|
+
|
98
|
+
# Will hold the Animation if animation is enabled for this
|
99
|
+
# video-preview.
|
100
|
+
animation = nil
|
101
|
+
|
102
|
+
if has_animation
|
103
|
+
animation = Animation.new(animation_name, ctx)
|
104
|
+
animation.timing_function = Animation::EASE
|
105
|
+
animation.duration = duration
|
106
|
+
|
107
|
+
table[:animation] = quote(animation)
|
108
|
+
end
|
109
|
+
|
98
110
|
html << table.to_helper
|
99
111
|
|
100
112
|
# Transparent spacer for preserving aspect ratio.
|
@@ -218,26 +230,24 @@ module Inkcite
|
|
218
230
|
# end of the animation.
|
219
231
|
percent = 0.0
|
220
232
|
|
221
|
-
keyframes = Animation::Keyframes.new(animation_name, ctx)
|
222
|
-
|
223
233
|
# Iterate through each frame and add two keyframes, the first
|
224
234
|
# being the time at which the frame appears plus another frame
|
225
235
|
# after the duration it should be on screen.
|
226
236
|
frames.each do |f|
|
227
237
|
this_frame_url = "url(#{f})"
|
228
238
|
|
229
|
-
|
239
|
+
animation.add_keyframe(percent, { BACKGROUND_IMAGE => this_frame_url })
|
230
240
|
percent += percent_per_frame
|
231
|
-
|
241
|
+
animation.add_keyframe(percent, { BACKGROUND_IMAGE => this_frame_url })
|
232
242
|
percent += percent_per_transition
|
233
243
|
|
234
244
|
end
|
235
245
|
|
236
246
|
# Transition back to the first frame.
|
237
|
-
|
247
|
+
animation.add_keyframe(100, { BACKGROUND_IMAGE => "url(#{first_frame})" })
|
238
248
|
|
239
249
|
# Add the keyframes to the styles array.
|
240
|
-
styles <<
|
250
|
+
styles << animation.to_keyframe_css
|
241
251
|
|
242
252
|
end
|
243
253
|
|
data/lib/inkcite/version.rb
CHANGED
data/lib/inkcite/view.rb
CHANGED
@@ -335,6 +335,12 @@ module Inkcite
|
|
335
335
|
tag_stack(tag).opts
|
336
336
|
end
|
337
337
|
|
338
|
+
# Returns the array of browser prefixes that need to be included in
|
339
|
+
# CSS styles based on which version of the email this is.
|
340
|
+
def prefixes
|
341
|
+
[ '', '-webkit-' ]
|
342
|
+
end
|
343
|
+
|
338
344
|
def preview?
|
339
345
|
@environment == :preview
|
340
346
|
end
|
@@ -432,9 +438,7 @@ module Inkcite
|
|
432
438
|
# Add external styles
|
433
439
|
html += external_styles
|
434
440
|
|
435
|
-
html << '<style type="text/css">'
|
436
441
|
html << inline_styles
|
437
|
-
html << '</style>'
|
438
442
|
html << '</head>'
|
439
443
|
|
440
444
|
# Intentionally not setting the link colors because those should be entirely
|
@@ -710,7 +714,7 @@ module Inkcite
|
|
710
714
|
|
711
715
|
def inline_google_fonts
|
712
716
|
|
713
|
-
|
717
|
+
css = ''
|
714
718
|
|
715
719
|
# Google Web Fonts support courtesy of
|
716
720
|
# http://www.emaildesignreview.com/html-email-coding/web-fonts-in-email-1482/
|
@@ -729,7 +733,7 @@ module Inkcite
|
|
729
733
|
# If you use @font-face in HTML email, Outlook 07/10/13 will default all
|
730
734
|
# text back to Times New Roman.
|
731
735
|
# http://www.emaildesignreview.com/html-email-coding/web-fonts-in-email-1482/
|
732
|
-
|
736
|
+
css << '@media screen {'
|
733
737
|
|
734
738
|
# Iterate through the configured fonts. Check to see if we've already cached
|
735
739
|
# Google's response. If not, retrieve it and add it to the
|
@@ -744,16 +748,16 @@ module Inkcite
|
|
744
748
|
end
|
745
749
|
end
|
746
750
|
|
747
|
-
|
751
|
+
css << font_cache[url]
|
748
752
|
end
|
749
|
-
|
753
|
+
css << '}'
|
750
754
|
|
751
755
|
# If the fontcache was updated, update it in our sekret file.
|
752
756
|
File.write(font_cache_path, font_cache.to_yaml) if updated
|
753
757
|
|
754
758
|
end
|
755
759
|
|
756
|
-
|
760
|
+
css
|
757
761
|
end
|
758
762
|
|
759
763
|
|
@@ -779,7 +783,7 @@ module Inkcite
|
|
779
783
|
code
|
780
784
|
end
|
781
785
|
|
782
|
-
def
|
786
|
+
def inline_reset_styles
|
783
787
|
|
784
788
|
reset = []
|
785
789
|
|
@@ -820,26 +824,57 @@ module Inkcite
|
|
820
824
|
# Reset the font on every cell to the default family.
|
821
825
|
reset << "td { font-family: #{self[Renderer::Base::FONT_FAMILY]}; }"
|
822
826
|
|
823
|
-
#
|
827
|
+
# VML-specific CSS needed only if VML was used in the email.
|
824
828
|
if vml_used?
|
825
829
|
reset << 'v\:* { behavior: url(#default#VML); display: inline-block; }'
|
826
830
|
reset << 'o\:* { behavior: url(#default#VML); display: inline-block; }'
|
827
831
|
end
|
828
832
|
|
829
|
-
reset
|
833
|
+
reset.join(NEW_LINE)
|
834
|
+
end
|
835
|
+
|
836
|
+
def inline_styles
|
837
|
+
|
838
|
+
# Separating <style> blocks to prevent Gmail from filtering
|
839
|
+
# the entire CSS section because of its strict parsing.
|
840
|
+
# https://emails.hteumeuleu.com/troubleshooting-gmails-responsive-design-support-ad124178bf81#.khhj4u4b5
|
841
|
+
style_blocks = []
|
842
|
+
|
843
|
+
# Add a section for the bootstrap/reset styles common to every email
|
844
|
+
# that address common rendering issues in many clients.
|
845
|
+
style_blocks << inline_reset_styles
|
846
|
+
|
847
|
+
# Web font styles need to be in their own block because
|
848
|
+
# they have multiple @ signs which Gmail doesn't like.
|
849
|
+
style_blocks << inline_google_fonts
|
830
850
|
|
831
851
|
# Responsive styles.
|
832
|
-
|
852
|
+
style_blocks << @media_query.to_css unless @media_query.blank?
|
833
853
|
|
834
|
-
|
854
|
+
# Filter the URI-based styles and add the remaining styles as a
|
855
|
+
# separate block. Possibly need to consider making these style
|
856
|
+
# blocks separate in the future - e.g. special effects blocks
|
857
|
+
# should probably be separated since there is a high likelihood
|
858
|
+
# of @ within @
|
859
|
+
style_blocks << self.styles.select { |s| !s.is_a?(URI::HTTP) }.join(NEW_LINE)
|
835
860
|
|
836
|
-
#
|
837
|
-
|
861
|
+
# Filter empty style blocks
|
862
|
+
style_blocks.select! { |s| !s.blank? }
|
838
863
|
|
839
|
-
#
|
840
|
-
|
841
|
-
|
842
|
-
|
864
|
+
# Minify each of the blocks
|
865
|
+
style_blocks.each { |s| Minifier.css(s, self) }
|
866
|
+
|
867
|
+
# Join all of the style blocks into a single block if this
|
868
|
+
# is not an email - otherwise, keep them separate.
|
869
|
+
style_blocks = [ style_blocks.join(NEW_LINE) ] unless email?
|
870
|
+
|
871
|
+
html = []
|
872
|
+
|
873
|
+
# Iterate through the style blocks and append them
|
874
|
+
style_blocks.each do |s|
|
875
|
+
html << '<style>'
|
876
|
+
html << s
|
877
|
+
html << '</style>'
|
843
878
|
end
|
844
879
|
|
845
880
|
html.join(NEW_LINE)
|
data/test/animation_spec.rb
CHANGED
@@ -7,31 +7,35 @@ describe Inkcite::Animation do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
it 'supports browser prefixing' do
|
10
|
-
Inkcite::
|
10
|
+
Inkcite::Renderer::Style.new(nil, @view, { :animation => 'video-frames 5s ease infinite' }).to_s.must_equal('-webkit-animation:video-frames 5s ease infinite;animation:video-frames 5s ease infinite')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'supports browser prefixing specific items only' do
|
14
|
+
Inkcite::Renderer::Style.new(nil, @view, { :left => '25%', :animation => 'video-frames 5s ease infinite' }).to_s.must_equal('-webkit-animation:video-frames 5s ease infinite;animation:video-frames 5s ease infinite;left:25%')
|
11
15
|
end
|
12
16
|
|
13
17
|
it 'can instantiate an animation keyframe' do
|
14
|
-
Inkcite::Animation::Keyframe.new(5, { :top => '-10px', :left => '22%' }).
|
18
|
+
Inkcite::Animation::Keyframe.new(5, @view, { :top => '-10px', :left => '22%' }).to_css('').must_equal('5% { left:22%;top:-10px }')
|
15
19
|
end
|
16
20
|
|
17
21
|
it 'can add style to an animation keyframe' do
|
18
|
-
keyframe = Inkcite::Animation::Keyframe.new(25)
|
22
|
+
keyframe = Inkcite::Animation::Keyframe.new(25, @view)
|
19
23
|
keyframe[:top] = '-15%'
|
20
24
|
keyframe[:left] = '78px'
|
21
|
-
keyframe.
|
25
|
+
keyframe.to_css('').must_equal('25% { left:78px;top:-15% }')
|
22
26
|
end
|
23
27
|
|
24
28
|
it 'can prefix a style on a keyframe' do
|
25
|
-
keyframe = Inkcite::Animation::Keyframe.new(33)
|
26
|
-
keyframe.
|
27
|
-
keyframe.
|
29
|
+
keyframe = Inkcite::Animation::Keyframe.new(33, @view, { :transform => 'rotate(14deg)' })
|
30
|
+
keyframe.to_css('').must_equal('33% { transform:rotate(14deg) }')
|
31
|
+
keyframe.to_css('-webkit-').must_equal('33% { -webkit-transform:rotate(14deg) }')
|
28
32
|
end
|
29
33
|
|
30
34
|
it 'can instantiate an animation and add keyframes' do
|
31
|
-
anim = Inkcite::Animation
|
32
|
-
anim
|
35
|
+
anim = Inkcite::Animation.new('snowflake7', @view)
|
36
|
+
anim.add_keyframe 5, { :top => '-10px', :left => '22%', :transform => 'rotate(14deg)' }
|
33
37
|
anim.add_keyframe 25, { :top => '100%', :left => '18%' }
|
34
|
-
anim.
|
38
|
+
anim.to_keyframe_css.must_equal(%Q(@keyframes snowflake7 {\n5% { left:22%;top:-10px;transform:rotate(14deg) }\n25% { left:18%;top:100% }\n}\n@-webkit-keyframes snowflake7 {\n5% { -webkit-transform:rotate(14deg);left:22%;top:-10px }\n25% { left:18%;top:100% }\n}\n))
|
35
39
|
end
|
36
40
|
|
37
41
|
|
@@ -0,0 +1,59 @@
|
|
1
|
+
describe Inkcite::Renderer::Background 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('{background src=missing.jpg}', @view)
|
9
|
+
@view.errors.must_include('Missing image (line 0) [src=missing.jpg]')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'warns when an outlook-specific image is missing' do
|
13
|
+
Inkcite::Renderer.render('{background outlook-src=also-missing.jpg}', @view)
|
14
|
+
@view.errors.must_include('Missing image (line 0) [src=also-missing.jpg]')
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'defaults to filling the available horizontal space' do
|
18
|
+
Inkcite::Renderer.render('{background src=https://i.imgur.com/YJOX1PC.png}{/background}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="background:url(https://i.imgur.com/YJOX1PC.png)" width=100%><tr><td><!--[if mso]><v:rect fill="t" stroke="f" 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"><![endif]--><div></div><!--[if mso]></v:textbox></v:rect><![endif]--></td></tr></table>')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'supports 100% width' do
|
22
|
+
Inkcite::Renderer.render('{background src=https://i.imgur.com/YJOX1PC.png width=100%}{/background}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="background:url(https://i.imgur.com/YJOX1PC.png)" width=100%><tr><td><!--[if mso]><v:rect fill="t" stroke="f" 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"><![endif]--><div></div><!--[if mso]></v:textbox></v:rect><![endif]--></td></tr></table>')
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'supports fill width' do
|
26
|
+
Inkcite::Renderer.render('{background src=https://i.imgur.com/YJOX1PC.png width=fill}{/background}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="background:url(https://i.imgur.com/YJOX1PC.png)" width=100%><tr><td><!--[if mso]><v:rect fill="t" stroke="f" 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"><![endif]--><div></div><!--[if mso]></v:textbox></v:rect><![endif]--></td></tr></table>')
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'supports an optional width in pixels' do
|
30
|
+
Inkcite::Renderer.render('{background src=https://i.imgur.com/YJOX1PC.png width=120}{/background}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="background:url(https://i.imgur.com/YJOX1PC.png)" width=120><tr><td><!--[if mso]><v:rect fill="t" stroke="f" 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"><![endif]--><div></div><!--[if mso]></v:textbox></v:rect><![endif]--></td></tr></table>')
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'supports an optional height in pixels' do
|
34
|
+
Inkcite::Renderer.render('{background src=https://i.imgur.com/YJOX1PC.png bgcolor=#7bceeb height=92 width=120}{/background}', @view).must_equal('<table bgcolor=#7bceeb border=0 cellpadding=0 cellspacing=0 height=92 style="background:#7bceeb url(https://i.imgur.com/YJOX1PC.png)" width=120><tr><td><!--[if mso]><v:rect fill="t" stroke="f" 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"><![endif]--><div></div><!--[if mso]></v:textbox></v:rect><![endif]--></td></tr></table>')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'supports an optional background color' do
|
38
|
+
Inkcite::Renderer.render('{background src=https://i.imgur.com/YJOX1PC.png bgcolor=#7bceeb width=120}{/background}', @view).must_equal('<table bgcolor=#7bceeb border=0 cellpadding=0 cellspacing=0 style="background:#7bceeb url(https://i.imgur.com/YJOX1PC.png)" width=120><tr><td><!--[if mso]><v:rect fill="t" stroke="f" 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"><![endif]--><div></div><!--[if mso]></v:textbox></v:rect><![endif]--></td></tr></table>')
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'supports the font attribute' do
|
42
|
+
Inkcite::Renderer.render('{background src=https://i.imgur.com/YJOX1PC.png font=large align=center}{/background}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="background:url(https://i.imgur.com/YJOX1PC.png)" width=100%><tr><td><!--[if mso]><v:rect fill="t" stroke="f" 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"><![endif]--><div style="color:#ff0000;font-family:serif;font-size:24px;font-weight:bold;line-height:24px;text-align:center"></div><!--[if mso]></v:textbox></v:rect><![endif]--></td></tr></table>')
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'supports font-related attributes' do
|
46
|
+
Inkcite::Renderer.render('{background src=https://i.imgur.com/YJOX1PC.png font-size=18 line-height=27}{/background}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="background:url(https://i.imgur.com/YJOX1PC.png)" width=100%><tr><td><!--[if mso]><v:rect fill="t" stroke="f" 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"><![endif]--><div style="font-size:18px;line-height:27px"></div><!--[if mso]></v:textbox></v:rect><![endif]--></td></tr></table>')
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'supports a custom mobile background' do
|
50
|
+
Inkcite::Renderer.render('{background src=https://i.imgur.com/YJOX1PC.png mobile-src="https://i.imgur.com/YJOX1PC-mobile.png" mobile-background-position="top" mobile-background-size="cover"}{/background}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 class="m1" style="background:url(https://i.imgur.com/YJOX1PC.png)" width=100%><tr><td><!--[if mso]><v:rect fill="t" stroke="f" 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"><![endif]--><div></div><!--[if mso]></v:textbox></v:rect><![endif]--></td></tr></table>')
|
51
|
+
@view.media_query.find_by_klass('m1').declaration_string.must_equal('background:url(https://i.imgur.com/YJOX1PC-mobile.png) top / cover no-repeat !important')
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'supports mobile padding' do
|
55
|
+
Inkcite::Renderer.render('{background src=background.jpg mobile-padding=15}{/background}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="background:url(images/background.jpg)" width=100%><tr><td class="m1"><!--[if mso]><v:rect fill="t" stroke="f" style="mso-width-percent:1000" xmlns:v="urn:schemas-microsoft-com:vml"><v:fill src="images/background.jpg" type="tile" /><v:textbox inset="0,0,0,0" style="mso-fit-shape-to-text:True"><![endif]--><div></div><!--[if mso]></v:textbox></v:rect><![endif]--></td></tr></table>')
|
56
|
+
@view.media_query.find_by_klass('m1').declaration_string.must_equal('padding:15px')
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|