inkcite 1.13.0 → 1.14.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/README.md +1 -1
- data/inkcite.gemspec +1 -0
- data/lib/inkcite.rb +1 -1
- data/lib/inkcite/cli/server.rb +31 -6
- data/lib/inkcite/facade.rb +6 -0
- data/lib/inkcite/{animation.rb → facade/animation.rb} +19 -56
- data/lib/inkcite/{renderer → facade}/element.rb +0 -0
- data/lib/inkcite/facade/keyframe.rb +83 -0
- data/lib/inkcite/{renderer → facade}/style.rb +4 -0
- data/lib/inkcite/minifier.rb +141 -57
- data/lib/inkcite/parser.rb +1 -1
- data/lib/inkcite/renderer.rb +2 -2
- data/lib/inkcite/renderer/background.rb +1 -1
- data/lib/inkcite/renderer/base.rb +1 -1
- data/lib/inkcite/renderer/container_base.rb +3 -4
- data/lib/inkcite/renderer/fireworks.rb +231 -0
- data/lib/inkcite/renderer/in_browser.rb +1 -2
- data/lib/inkcite/renderer/responsive.rb +29 -2
- data/lib/inkcite/renderer/snow.rb +1 -1
- data/lib/inkcite/renderer/special_effect.rb +66 -29
- data/lib/inkcite/renderer/table_base.rb +6 -0
- data/lib/inkcite/renderer/td.rb +7 -2
- data/lib/inkcite/renderer/video_preview.rb +7 -1
- data/lib/inkcite/util.rb +56 -0
- data/lib/inkcite/version.rb +1 -1
- data/lib/inkcite/view.rb +42 -1
- data/test/animation_spec.rb +38 -5
- data/test/renderer/div_spec.rb +30 -0
- data/test/renderer/td_spec.rb +25 -0
- data/test/renderer/video_preview_spec.rb +1 -1
- data/test/util_spec.rb +11 -0
- metadata +24 -5
data/lib/inkcite/parser.rb
CHANGED
@@ -22,7 +22,7 @@ module Inkcite
|
|
22
22
|
# Provide the block with the area that was matched, sans wrapper brackets.
|
23
23
|
# Replace the brackets and original value with the block's results.
|
24
24
|
result = yield(match[1].to_s) || EMPTY_STRING
|
25
|
-
str[offset.first, offset.last - offset.first] = result
|
25
|
+
str[offset.first, offset.last - offset.first] = result.to_s
|
26
26
|
|
27
27
|
# Ensure we don't infinite loop.
|
28
28
|
failsafe += 1
|
data/lib/inkcite/renderer.rb
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
require_relative 'renderer/base'
|
2
|
-
require_relative 'renderer/element'
|
3
2
|
require_relative 'renderer/responsive'
|
4
3
|
require_relative 'renderer/container_base'
|
5
4
|
require_relative 'renderer/special_effect'
|
6
5
|
require_relative 'renderer/image_base'
|
7
6
|
require_relative 'renderer/table_base'
|
8
|
-
require_relative 'renderer/style'
|
9
7
|
|
10
8
|
require_relative 'renderer/background'
|
11
9
|
require_relative 'renderer/button'
|
12
10
|
require_relative 'renderer/div'
|
11
|
+
require_relative 'renderer/fireworks'
|
13
12
|
require_relative 'renderer/footnote'
|
14
13
|
require_relative 'renderer/google_analytics'
|
15
14
|
require_relative 'renderer/image'
|
@@ -174,6 +173,7 @@ module Inkcite
|
|
174
173
|
:button => Button.new,
|
175
174
|
:div => Div.new,
|
176
175
|
:facebook => Social::Facebook.new,
|
176
|
+
:fireworks => Fireworks.new,
|
177
177
|
:footnote => Footnote.new,
|
178
178
|
:footnotes => Footnotes.new,
|
179
179
|
:google => GoogleAnalytics.new,
|
@@ -145,7 +145,7 @@ module Inkcite
|
|
145
145
|
BACKGROUND_POSITION, :border, BORDER_BOTTOM, BORDER_LEFT, BORDER_RADIUS, BORDER_RIGHT,
|
146
146
|
BORDER_SPACING, BORDER_TOP, :mobile, MOBILE_BGCOLOR, MOBILE_BACKGROUND, MOBILE_BACKGROUND_COLOR,
|
147
147
|
MOBILE_BACKGROUND_IMAGE, MOBILE_BACKGROUND_REPEAT, MOBILE_BACKGROUND_POSITION, MOBILE_PADDING,
|
148
|
-
MOBILE_SRC, MOBILE_BACKGROUND_SIZE
|
148
|
+
MOBILE_SRC, MOBILE_BACKGROUND_SIZE, MOBILE_WIDTH
|
149
149
|
]
|
150
150
|
|
151
151
|
end
|
@@ -168,7 +168,7 @@ module Inkcite
|
|
168
168
|
dir_opt_key = add_directional_suffix(opt_key, dir)
|
169
169
|
dir_css_key = add_directional_suffix(css_key, dir)
|
170
170
|
value = opt[dir_opt_key]
|
171
|
-
next if
|
171
|
+
next if value.blank?
|
172
172
|
|
173
173
|
value = px(value) if as_px
|
174
174
|
into[dir_css_key] = value
|
@@ -18,10 +18,6 @@ module Inkcite
|
|
18
18
|
padding = opt[:padding]
|
19
19
|
element.style[:padding] = px(padding) unless none?(padding)
|
20
20
|
|
21
|
-
# Supports custom padding on mobile - e.g. mobile-padding="15px 5px"
|
22
|
-
mobile_padding = opt[MOBILE_PADDING]
|
23
|
-
element.mobile_style[:padding] = px(mobile_padding) unless none?(mobile_padding)
|
24
|
-
|
25
21
|
# Vertical alignment - top, middle, bottom.
|
26
22
|
valign = opt[:valign]
|
27
23
|
element.style[VERTICAL_ALIGN] = valign unless none?(valign)
|
@@ -33,6 +29,9 @@ module Inkcite
|
|
33
29
|
# style to the element.
|
34
30
|
element.style[WHITE_SPACE] = :nowrap if opt[:nowrap]
|
35
31
|
|
32
|
+
# Support for mobile-padding and mobile-padding-(direction)
|
33
|
+
mix_mobile_padding element, opt, ctx
|
34
|
+
|
36
35
|
mix_responsive element, opt, ctx
|
37
36
|
|
38
37
|
element.to_s
|
@@ -0,0 +1,231 @@
|
|
1
|
+
module Inkcite
|
2
|
+
module Renderer
|
3
|
+
|
4
|
+
# Animated CSS fireworks special effect based on the technique
|
5
|
+
# by Eddie Lin https://codepen.io/yshlin/pen/ylDEk
|
6
|
+
class Fireworks < SpecialEffect
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
# Each firework will move this many positions during the
|
11
|
+
# entire animation.
|
12
|
+
TOTAL_POSITIONS = 5
|
13
|
+
|
14
|
+
# The number of hue degrees to randomly alter the hue of each spark
|
15
|
+
HUE_RANGE = :'hue-range'
|
16
|
+
|
17
|
+
# Names of the attributes controlling min and max explosion size.
|
18
|
+
RADIUS_MIN = :'min-radius'
|
19
|
+
RADIUS_MAX = :'max-radius'
|
20
|
+
|
21
|
+
# Attributes used for color generation
|
22
|
+
SATURATION = 100
|
23
|
+
LUMINANCE = 50
|
24
|
+
|
25
|
+
def config_effect_context sfx
|
26
|
+
|
27
|
+
count = sfx.count
|
28
|
+
|
29
|
+
# Total number of firework instances multiplied by the number
|
30
|
+
# of positions each firework will cycle through.
|
31
|
+
position_count = TOTAL_POSITIONS * count
|
32
|
+
positions = sfx.equal_distribution(sfx.position_range, position_count)
|
33
|
+
|
34
|
+
sfx[:x_positions] = positions
|
35
|
+
sfx[:y_positions] = positions.dup
|
36
|
+
|
37
|
+
# Equal distribution of hues based on the number of fireworks
|
38
|
+
# if the rainbow option is selected
|
39
|
+
sfx[:hues] = sfx.equal_distribution(0..360, count)
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_explosion_animation n, hue, duration, delay, sfx
|
44
|
+
|
45
|
+
# Calculate the radius size for this explosion
|
46
|
+
min_radius = sfx[RADIUS_MIN].to_i
|
47
|
+
max_radius = sfx[RADIUS_MAX].to_i
|
48
|
+
radius_range = (min_radius..max_radius)
|
49
|
+
radius = rand(radius_range).round(0)
|
50
|
+
half_radius = radius / 2.0
|
51
|
+
|
52
|
+
hue_range = (sfx[HUE_RANGE] || 40).to_i
|
53
|
+
hue_range_2x = hue_range * 2
|
54
|
+
|
55
|
+
sparks = sfx[:sparks].to_i
|
56
|
+
|
57
|
+
box_shadow = sparks.times.collect do |n|
|
58
|
+
|
59
|
+
# Pick a random position for this spark to move to
|
60
|
+
x = (rand(radius) - half_radius).round(0)
|
61
|
+
y = (rand(radius) - half_radius).round(0)
|
62
|
+
|
63
|
+
# Randomly pick a slightly different hue for this spark
|
64
|
+
_hue = hue + hue_range - rand(hue_range_2x)
|
65
|
+
color = Inkcite::Util::hsl_to_color(_hue, SATURATION, LUMINANCE)
|
66
|
+
|
67
|
+
"#{px(x)} #{px(y)} #{color}"
|
68
|
+
end
|
69
|
+
|
70
|
+
anim = Inkcite::Animation.new(sfx.animation_class_name(n, 'bang'), sfx.ctx)
|
71
|
+
anim.duration = duration
|
72
|
+
anim.delay = delay if delay > 0
|
73
|
+
anim.timing_function = Inkcite::Animation::EASE_OUT
|
74
|
+
anim.add_keyframe 100, { BOX_SHADOW => box_shadow.join(', ') }
|
75
|
+
|
76
|
+
sfx.animations << anim
|
77
|
+
|
78
|
+
anim
|
79
|
+
end
|
80
|
+
|
81
|
+
def create_gravity_animation sfx
|
82
|
+
|
83
|
+
anim = Animation.new('gravity', sfx.ctx)
|
84
|
+
|
85
|
+
# All fireworks fade to zero opacity and size by the end of the gravity cycle.
|
86
|
+
keyframe = anim.add_keyframe 100, { :opacity => 0, :width => 0, :height => 0 }
|
87
|
+
|
88
|
+
# Check to see if gravity has been specified for the fireworks. If so
|
89
|
+
# apply it as a vertical translation (positive equals downward)
|
90
|
+
gravity = sfx[:gravity].to_i
|
91
|
+
keyframe[:transform] = "translateY(#{px(gravity)})" if gravity != 0
|
92
|
+
|
93
|
+
sfx.animations << anim
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
def create_position_animation n, duration, delay, sfx
|
98
|
+
|
99
|
+
# This is the percentage amount of the total animation that will
|
100
|
+
# be spent in each position.
|
101
|
+
keyframe_duration = (100 / TOTAL_POSITIONS.to_f)
|
102
|
+
|
103
|
+
anim = Inkcite::Animation.new(sfx.animation_class_name(n, 'position'), sfx.ctx)
|
104
|
+
anim.duration = duration
|
105
|
+
anim.delay = delay if delay > 0
|
106
|
+
anim.timing_function = Inkcite::Animation::LINEAR
|
107
|
+
|
108
|
+
x_positions = sfx[:x_positions]
|
109
|
+
y_positions = sfx[:y_positions]
|
110
|
+
|
111
|
+
percent = 0
|
112
|
+
TOTAL_POSITIONS.times do |n|
|
113
|
+
|
114
|
+
# Pick a random position for this firework
|
115
|
+
top = y_positions.delete_at(rand(y_positions.length))
|
116
|
+
left = x_positions.delete_at(rand(x_positions.length))
|
117
|
+
|
118
|
+
keyframe = anim.add_keyframe(percent, { :top => pct(top), :left => pct(left) })
|
119
|
+
keyframe.duration = keyframe_duration - 0.1
|
120
|
+
|
121
|
+
percent += keyframe_duration
|
122
|
+
end
|
123
|
+
|
124
|
+
sfx.animations << anim
|
125
|
+
|
126
|
+
anim
|
127
|
+
end
|
128
|
+
|
129
|
+
protected
|
130
|
+
|
131
|
+
def config_all_children style, sfx
|
132
|
+
|
133
|
+
# If all of the sparks in the firework have the same size
|
134
|
+
# (e.g. min-size equals max-size) then save some CSS space
|
135
|
+
# by defining it once for all children.
|
136
|
+
if sfx.same_size?
|
137
|
+
style[:width] = px(sfx.min_size)
|
138
|
+
style[:height] = px(sfx.min_size)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Make sure all explosions start off-screen.
|
142
|
+
style[:top] = "-#{px(sfx.max_size)}"
|
143
|
+
|
144
|
+
style[BORDER_RADIUS] = '50%'
|
145
|
+
|
146
|
+
sparks = sfx[:sparks].to_i
|
147
|
+
|
148
|
+
# All sparks start with a box shadow at their exact center,
|
149
|
+
# all in white.
|
150
|
+
box_shadow = sparks.times.collect { |n| '0 0 #fff' }
|
151
|
+
style[BOX_SHADOW] = box_shadow.join(', ')
|
152
|
+
|
153
|
+
# Create the global gravity animation that is consistent for all fireworks.
|
154
|
+
# There is no variance in this animation so it is created and added to the
|
155
|
+
# context only once.
|
156
|
+
create_gravity_animation(sfx)
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
def config_child n, child, style, animation, sfx
|
161
|
+
|
162
|
+
# If all of the fireworks are different possible sizes
|
163
|
+
# then pick a random size for this child.
|
164
|
+
unless sfx.same_size?
|
165
|
+
size = sfx.rand_size
|
166
|
+
style[:width] = px(size)
|
167
|
+
style[:height] = px(size)
|
168
|
+
end
|
169
|
+
|
170
|
+
# If rainbow is specified, choose the next color in the array - otherwise
|
171
|
+
# choose a random hue unless a specific one has been specified.
|
172
|
+
hue = sfx[:rainbow] ? sfx[:hues][n] : (sfx[:hue] || rand(360)).to_i
|
173
|
+
|
174
|
+
# Randomly pick a color for this explosion by choosing a
|
175
|
+
# random hue and then converting it to a hex color
|
176
|
+
color = Inkcite::Util::hsl_to_color(hue, 100, 50)
|
177
|
+
style[BACKGROUND_COLOR] = color
|
178
|
+
|
179
|
+
# After the first child, each firework should have a random
|
180
|
+
# delay before its animation starts - giving the different
|
181
|
+
# fireworks a staggered launch.
|
182
|
+
delay = n > 0 ? 0.25 + rand(sfx.count).round(2) : 0
|
183
|
+
|
184
|
+
# This is the total amount of time it will take the firework to
|
185
|
+
# move through each of its positions.
|
186
|
+
position_speed = sfx.rand_speed
|
187
|
+
|
188
|
+
# This is the speed the firework animates it's explosion and gravity
|
189
|
+
# components - which need to repeat n-number of times based on the
|
190
|
+
# total number of positions.
|
191
|
+
explosion_speed = (position_speed / TOTAL_POSITIONS.to_f).round(2)
|
192
|
+
|
193
|
+
gravity_animation = Inkcite::Animation.new('gravity', sfx.ctx)
|
194
|
+
gravity_animation.duration = explosion_speed
|
195
|
+
gravity_animation.delay = delay if n > 0
|
196
|
+
gravity_animation.timing_function = Inkcite::Animation::EASE_IN
|
197
|
+
|
198
|
+
composite_animation = Inkcite::Animation::Composite.new
|
199
|
+
composite_animation << create_explosion_animation(n, hue, explosion_speed, delay, sfx)
|
200
|
+
composite_animation << gravity_animation
|
201
|
+
composite_animation << create_position_animation(n, position_speed, delay, sfx)
|
202
|
+
|
203
|
+
style[:animation] = composite_animation
|
204
|
+
|
205
|
+
# # Each firework consists of three separate animations - one to animate
|
206
|
+
# # the explosion, one to fade out/apply gravity and one to move the
|
207
|
+
# # firework through it's fixed positions.
|
208
|
+
# style[:animation] = "1s bang ease-out infinite, 1s gravity ease-in infinite, #{TOTAL_POSITIONS}s position linear infinite"
|
209
|
+
|
210
|
+
# style[ANIMATION_DURATION] = "#{explosion_speed}s, #{explosion_speed}s, #{position_speed}s"
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
def defaults opt, ctx
|
215
|
+
{
|
216
|
+
:bgcolor => '#000000',
|
217
|
+
:sparks => 50,
|
218
|
+
:count => 2,
|
219
|
+
:gravity => 200,
|
220
|
+
RADIUS_MIN => 150,
|
221
|
+
RADIUS_MAX => 400,
|
222
|
+
SIZE_MIN => 10,
|
223
|
+
SIZE_MAX => 10,
|
224
|
+
SPEED_MIN => 5,
|
225
|
+
SPEED_MAX => 10,
|
226
|
+
}
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
module Inkcite
|
3
2
|
module Renderer
|
4
3
|
class InBrowser < Base
|
@@ -20,7 +19,7 @@ module Inkcite
|
|
20
19
|
color = opt[:color]
|
21
20
|
|
22
21
|
# Optional call-to-action override - otherwise defaults to view in browser.
|
23
|
-
cta = opt[:cta] || ctx.production?? 'View
|
22
|
+
cta = opt[:cta] || ctx.production?? 'View in Browser' : 'Preview in Browser'
|
24
23
|
|
25
24
|
id = opt[:id] || 'in-browser'
|
26
25
|
|
@@ -28,8 +28,9 @@ module Inkcite
|
|
28
28
|
MOBILE_SRC = :'mobile-src'
|
29
29
|
|
30
30
|
# Other mobile-specific properties
|
31
|
+
MOBILE_HEIGHT = :'mobile-height'
|
31
32
|
MOBILE_PADDING = :'mobile-padding'
|
32
|
-
|
33
|
+
MOBILE_WIDTH = :'mobile-width'
|
33
34
|
|
34
35
|
class Rule
|
35
36
|
|
@@ -241,8 +242,28 @@ module Inkcite
|
|
241
242
|
mix_directional element, element.mobile_style, opt, ctx, MOBILE_MARGIN, :margin, true
|
242
243
|
end
|
243
244
|
|
245
|
+
def mix_mobile_padding element, opt, ctx
|
246
|
+
mix_directional element, element.mobile_style, opt, ctx, MOBILE_PADDING, :padding, true
|
247
|
+
end
|
248
|
+
|
249
|
+
# A separate method for mixing in text alignment because the table cell
|
250
|
+
# helper handles alignment different from normal container elements.
|
251
|
+
def mix_mobile_text_align element, opt, ctx
|
252
|
+
|
253
|
+
# Support for mobile-text-align
|
254
|
+
align = opt[MOBILE_TEXT_ALIGN]
|
255
|
+
element.mobile_style[TEXT_ALIGN] = align unless none?(align)
|
256
|
+
|
257
|
+
end
|
258
|
+
|
244
259
|
def mix_responsive element, opt, ctx, klass=nil
|
245
260
|
|
261
|
+
mobile_style = opt[MOBILE_STYLE]
|
262
|
+
ctx.error 'mobile-style is no longer supported', { :element => element.to_s, MOBILE_STYLE => mobile_style } unless mobile_style.blank?
|
263
|
+
|
264
|
+
mobile_display = opt[MOBILE_DISPLAY]
|
265
|
+
element.mobile_style[:display] = mobile_display unless none?(mobile_display)
|
266
|
+
|
246
267
|
# Apply the "mobile" attribute or use the override if one was provided.
|
247
268
|
mix_responsive_klass element, opt, ctx, klass || opt[:mobile]
|
248
269
|
|
@@ -398,6 +419,11 @@ module Inkcite
|
|
398
419
|
|
399
420
|
end
|
400
421
|
|
422
|
+
def mix_text_align element, opt, ctx
|
423
|
+
super
|
424
|
+
mix_mobile_text_align element, opt, ctx
|
425
|
+
end
|
426
|
+
|
401
427
|
def unique_klass ctx
|
402
428
|
'm%1d' % ctx.unique_id(:m)
|
403
429
|
end
|
@@ -406,9 +432,10 @@ module Inkcite
|
|
406
432
|
|
407
433
|
# Attribute used to declare custom mobile styles for an element.
|
408
434
|
MOBILE_BORDER = :'mobile-border'
|
435
|
+
MOBILE_DISPLAY = :'mobile-display'
|
409
436
|
MOBILE_MARGIN = :'mobile-margin'
|
410
437
|
MOBILE_STYLE = :'mobile-style'
|
411
|
-
|
438
|
+
MOBILE_TEXT_ALIGN = :'mobile-text-align'
|
412
439
|
|
413
440
|
# Universal CSS selector.
|
414
441
|
UNIVERSAL = '*'
|
@@ -6,7 +6,7 @@ module Inkcite
|
|
6
6
|
# common to special effects like snow and sparkle.
|
7
7
|
class EffectContext
|
8
8
|
|
9
|
-
attr_reader :uuid
|
9
|
+
attr_reader :uuid, :animations
|
10
10
|
|
11
11
|
# Expose the opt and ctx attributes
|
12
12
|
attr_reader :opt, :ctx
|
@@ -31,14 +31,26 @@ module Inkcite
|
|
31
31
|
# this special effect.
|
32
32
|
@uuid = ctx.unique_id(:sfx)
|
33
33
|
|
34
|
+
# Will hold all of the Animations while the children are
|
35
|
+
# assembled and then added to the styles array at the end
|
36
|
+
# so that all keyframes are together in the source.
|
37
|
+
@animations = []
|
38
|
+
|
34
39
|
end
|
35
40
|
|
36
41
|
def all_children_class_name
|
37
42
|
obfuscate_class_names? ? "sfx#{@uuid}c" : "#{@tag}#{@uuid}-children"
|
38
43
|
end
|
39
44
|
|
40
|
-
def animation_class_name child_index
|
41
|
-
|
45
|
+
def animation_class_name child_index, suffix=nil
|
46
|
+
|
47
|
+
base = obfuscate_class_names? ? "#{@tag}#{@uuid}-anim#{child_index + 1}" : "sfx#{@uuid}a#{child_index + 1}"
|
48
|
+
unless suffix.blank?
|
49
|
+
base << '-'
|
50
|
+
base << (obfuscate_class_names? ? suffix[0] : suffix)
|
51
|
+
end
|
52
|
+
|
53
|
+
base
|
42
54
|
end
|
43
55
|
|
44
56
|
def child_class_name child_index
|
@@ -53,19 +65,19 @@ module Inkcite
|
|
53
65
|
# of snowflakes or sparkles in the animation. :flakes and :sparks are
|
54
66
|
# technically deprecated.
|
55
67
|
def count
|
56
|
-
|
68
|
+
@opt[:count].to_i
|
57
69
|
end
|
58
70
|
|
59
|
-
def equal_distribution qty
|
71
|
+
def equal_distribution range, qty
|
60
72
|
|
61
73
|
# Space the children generally equally across the width of the
|
62
74
|
# container div. Random distribution sometimes ends up with
|
63
75
|
# children clumped at one edge or the other.
|
64
|
-
spacing =
|
76
|
+
spacing = (range.last - range.first) / qty.to_f
|
65
77
|
|
66
78
|
# Now build up a pool of equally-spaced starting positions.
|
67
79
|
# TODO: This is probably a perfect spot to use inject()
|
68
|
-
start_left = spacing / 2.0
|
80
|
+
start_left = range.first + (spacing / 2.0)
|
69
81
|
|
70
82
|
# This array will hold all of the positions
|
71
83
|
positions = [start_left]
|
@@ -74,13 +86,17 @@ module Inkcite
|
|
74
86
|
# spacing and push onto the list.
|
75
87
|
(qty - 1).times { |f| positions << start_left += spacing }
|
76
88
|
|
77
|
-
positions
|
89
|
+
positions.collect { |p| p.round(0) }
|
78
90
|
end
|
79
91
|
|
80
92
|
def height
|
81
93
|
@opt[:height].to_i
|
82
94
|
end
|
83
95
|
|
96
|
+
def insets
|
97
|
+
@opt[:insets].to_i
|
98
|
+
end
|
99
|
+
|
84
100
|
def max_opacity
|
85
101
|
@opt[OPACITY_MAX].to_f
|
86
102
|
end
|
@@ -106,7 +122,7 @@ module Inkcite
|
|
106
122
|
end
|
107
123
|
|
108
124
|
def obfuscate_class_names?
|
109
|
-
|
125
|
+
@ctx.production?
|
110
126
|
end
|
111
127
|
|
112
128
|
def opacity_range
|
@@ -137,6 +153,10 @@ module Inkcite
|
|
137
153
|
(-270..270)
|
138
154
|
end
|
139
155
|
|
156
|
+
def same_size?
|
157
|
+
min_size == max_size
|
158
|
+
end
|
159
|
+
|
140
160
|
def size_range
|
141
161
|
(min_size..max_size)
|
142
162
|
end
|
@@ -159,18 +179,24 @@ module Inkcite
|
|
159
179
|
@src
|
160
180
|
end
|
161
181
|
|
182
|
+
def position_range
|
183
|
+
min = POSITION_FLOOR + insets
|
184
|
+
max = POSITION_CEIL - insets
|
185
|
+
(min..max)
|
186
|
+
end
|
187
|
+
|
162
188
|
# Creates a permanent list of positions (as percentages of the wrap container's
|
163
189
|
# total width) which can be used for starting or ending position to equally
|
164
190
|
# space animated elements.
|
165
191
|
def positions_x
|
166
|
-
@positions_x ||= equal_distribution(count)
|
192
|
+
@positions_x ||= equal_distribution(position_range, count)
|
167
193
|
end
|
168
194
|
|
169
195
|
# Creates a permanent list of positions (as percentages of the wrap container's
|
170
196
|
# total height) which can be used for starting or ending position to equally
|
171
197
|
# space animated elements.
|
172
198
|
def positions_y
|
173
|
-
@positions_y ||= equal_distribution(count)
|
199
|
+
@positions_y ||= equal_distribution(position_range, count)
|
174
200
|
end
|
175
201
|
|
176
202
|
def start_time child_index
|
@@ -247,6 +273,10 @@ module Inkcite
|
|
247
273
|
# at the same time.
|
248
274
|
create_child_elements html, styles, sfx
|
249
275
|
|
276
|
+
# Append all of the Keyframes to the end of the styles, now that
|
277
|
+
# the individual children are configured.
|
278
|
+
sfx.animations.each { |a| styles << a.to_keyframe_css }
|
279
|
+
|
250
280
|
# Push the completed list of styles into the context's stack.
|
251
281
|
ctx.styles << styles.join("\n")
|
252
282
|
|
@@ -274,10 +304,14 @@ module Inkcite
|
|
274
304
|
OPACITY_MAX = :'max-opacity'
|
275
305
|
OPACITY_CEIL = 1.0
|
276
306
|
|
307
|
+
# Static constants for animation-specific CSS
|
308
|
+
ANIMATION_DELAY = :'animation-delay'
|
309
|
+
ANIMATION_DURATION = :'animation-duration'
|
310
|
+
|
277
311
|
# The extending class can override this method to perform any
|
278
312
|
# additional configuration on the style that affects all
|
279
313
|
# children in the animation.
|
280
|
-
def
|
314
|
+
def config_all_children style, sfx
|
281
315
|
# This space left intentionally blank
|
282
316
|
end
|
283
317
|
|
@@ -333,7 +367,7 @@ module Inkcite
|
|
333
367
|
|
334
368
|
# Provide the extending class with a chance to apply additional
|
335
369
|
# styles to all children.
|
336
|
-
|
370
|
+
config_all_children style, sfx
|
337
371
|
|
338
372
|
styles << style
|
339
373
|
|
@@ -343,11 +377,6 @@ module Inkcite
|
|
343
377
|
# CSS classes to them allowing each to be sized, animated uniquely.
|
344
378
|
def create_child_elements html, styles, sfx
|
345
379
|
|
346
|
-
# Will hold all of the Animations while the children are
|
347
|
-
# assembled and then added to the styles array at the end
|
348
|
-
# so that all keyframes are together in the source.
|
349
|
-
animations = []
|
350
|
-
|
351
380
|
sfx.count.times do |n|
|
352
381
|
|
353
382
|
child_class_name = sfx.child_class_name(n)
|
@@ -365,20 +394,28 @@ module Inkcite
|
|
365
394
|
# and its style.
|
366
395
|
config_child n, child, style, animation, sfx
|
367
396
|
|
368
|
-
#
|
369
|
-
# style - this adds itself with the appropriate browser prefixes.
|
370
|
-
style[:animation] = animation
|
371
|
-
|
372
|
-
# Inject the various pieces into the appropriate lists.
|
397
|
+
# Add the child's HTML element into the email.
|
373
398
|
html << child.to_s + '</div>'
|
374
|
-
styles << style
|
375
|
-
animations << animation
|
376
399
|
|
377
|
-
|
400
|
+
# If the extending class actually defined an animation for this child
|
401
|
+
# then assign it and add it to the list of animations to be appended
|
402
|
+
# after the styles are injected.
|
403
|
+
unless animation.blank?
|
378
404
|
|
379
|
-
|
380
|
-
|
381
|
-
|
405
|
+
sfx.animations << animation
|
406
|
+
|
407
|
+
# If the extending class didn't assign the animation already, then
|
408
|
+
# assign it to the child's style - this adds itself with the appropriate
|
409
|
+
# browser prefixes.
|
410
|
+
style[:animation] = animation if style[:animation].blank?
|
411
|
+
|
412
|
+
end
|
413
|
+
|
414
|
+
# Append the child's custom style, unless blank (meaning the extending
|
415
|
+
# class did not customize the child's styles directly).
|
416
|
+
styles << style unless style.blank?
|
417
|
+
|
418
|
+
end
|
382
419
|
|
383
420
|
end
|
384
421
|
|