inkcite 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dff1fb6ce80d821e6c797a6c691e904ed6dfb60d
4
- data.tar.gz: dcea60b5e3efe7edabc97186822e09e8cf43c8d5
3
+ metadata.gz: b0303ddbd80b228a0fd359eb646834a24e0c8e37
4
+ data.tar.gz: 720d1a683829b80e35e1b21162ab0e54120763af
5
5
  SHA512:
6
- metadata.gz: 8b19819db8870689817a7947159c7d30ff14e7a237c485dd42d43443691da47f2af0573e34df9f1873cdb14c8a20b71516ff0a23e6b9abdf06eac3747fd7a315
7
- data.tar.gz: 118adc599578c2d779d841ea78c8808a8a49334b084809e48eae9e6499e505d93218e5c5ab25026c7cf14b34ec930c39b4bc45401a928d3562eaed823f43aa80
6
+ metadata.gz: 0babd93ce009462a59b296af9c5675d4c41e2d2e96c307bbbc7bac093496bdd523bde613b823a18d450c576ca57a6bfe5e120b35afdbf099188539db39741a57
7
+ data.tar.gz: 915e2f2941af36147805a1c0b5ac3383c28b4933bd08eeb20d560eab3b735364b205c236d773f7700556098af3179fffed5f57d7214635a1225b912e81d0d9ef
@@ -39,6 +39,15 @@ smtp:
39
39
  password: ''
40
40
  from: 'Your Name <email@domain.com>'
41
41
 
42
+ # Mailgun settings for sending previews via their 3x faster API. Sign up for
43
+ # a free account and retrieve your API key and sending domain from your
44
+ # Mailgun account dashboard.
45
+ #
46
+ # mailgun:
47
+ # api-key: 'key-your-api-key'
48
+ # domain: 'mg.sending-domain.com'
49
+ # from: 'Your Name <email@domain.com>'
50
+
42
51
  # Specify the distribution lists for preview versions of your email.
43
52
  recipients:
44
53
  client:
@@ -13,7 +13,7 @@ require_relative 'renderer/in_browser'
13
13
  require_relative 'renderer/increment'
14
14
  require_relative 'renderer/like'
15
15
  require_relative 'renderer/link'
16
- require_relative 'renderer/litmus'
16
+ require_relative 'renderer/litmus_analytics'
17
17
  require_relative 'renderer/lorem'
18
18
  require_relative 'renderer/mobile_image'
19
19
  require_relative 'renderer/mobile_style'
@@ -161,7 +161,7 @@ module Inkcite
161
161
  :'in-browser' => InBrowser.new,
162
162
  :include => Partial.new,
163
163
  :like => Like.new,
164
- :litmus => Litmus.new,
164
+ :litmus => LitmusAnalytics.new,
165
165
  :lorem => Lorem.new,
166
166
  :'mobile-img' => MobileImage.new,
167
167
  :'mobile-style' => MobileStyle.new,
@@ -17,10 +17,16 @@ module Inkcite
17
17
  # when the {footnotes} tag is rendered.
18
18
  attr_reader :text
19
19
 
20
- def initialize id, symbol, text
20
+ # True if this footnote is active. By default all footnotes are
21
+ # activate but those read from footnotes.tsv are inactive until
22
+ # referenced in the source.
23
+ attr_accessor :active
24
+
25
+ def initialize id, symbol, text, active=true
21
26
  @id = id
22
27
  @symbol = symbol.to_s
23
28
  @text = text
29
+ @active = active
24
30
  end
25
31
 
26
32
  def number
@@ -33,6 +39,10 @@ module Inkcite
33
39
  @symbol == @symbol.to_i.to_s
34
40
  end
35
41
 
42
+ def symbol=symbol
43
+ @symbol = symbol.to_s
44
+ end
45
+
36
46
  def symbol?
37
47
  !numeric?
38
48
  end
@@ -59,19 +69,13 @@ module Inkcite
59
69
  # this isn't specified count the number of existing numeric footnotes
60
70
  # and increment it for this new footnote's symbol.
61
71
  symbol = opt[:symbol]
62
- if symbol.blank?
63
-
64
- # Grab the last numeric footnote that was specified and, assuming
65
- # there is one, increment the count. Otherwise, start the count
66
- # off at one.
67
- last_instance = ctx.footnotes.select(&:numeric?).last
68
- symbol = last_instance.nil? ? 1 : last_instance.symbol.to_i + 1
69
-
70
- end
71
72
 
72
73
  # Grab the text associated with this footnote.
73
74
  text = opt[:text]
74
- ctx.error("Footnote requires text attribute", { :id => id, :symbol => symbol }) if text.blank?
75
+ if text.blank?
76
+ ctx.error("Footnote requires text attribute", { :id => id, :symbol => symbol })
77
+ return
78
+ end
75
79
 
76
80
  # Create a new Footnote instance
77
81
  instance = Instance.new(id, symbol, text)
@@ -81,6 +85,24 @@ module Inkcite
81
85
 
82
86
  end
83
87
 
88
+ # Check to see if the footnote's symbol is blank (either because one
89
+ # wasn't defined in the source.html or because the one read from the
90
+ # footnotes.tsv had no symbol associated with it) and if so, generate
91
+ # one based on the number of previously declared numeric footnotes.
92
+ if instance.symbol.blank?
93
+
94
+ # Grab the last numeric footnote that was specified and, assuming
95
+ # there is one, increment the count. Otherwise, start the count
96
+ # off at one.
97
+ last_instance = ctx.footnotes.select(&:numeric?).last
98
+ instance.symbol = last_instance.nil? ? 1 : last_instance.symbol.to_i + 1
99
+
100
+ end
101
+
102
+ # Make sure the instance is marked as having been used so it will
103
+ # appear in the {footnotes} rendering.
104
+ instance.active = true
105
+
84
106
  # Allow footnotes to be defined without showing a symbol
85
107
  hidden = opt[:hidden].to_i == 1
86
108
  "#{instance.symbol}" unless hidden
@@ -94,6 +116,10 @@ module Inkcite
94
116
  # Nothing to do if footnotes are blank.
95
117
  return if ctx.footnotes.blank?
96
118
 
119
+ # Grab the active footnotes.
120
+ active_footnotes = ctx.footnotes.select(&:active)
121
+ return if active_footnotes.blank?
122
+
97
123
  # Check to see if a template has been provided. Otherwise use a default one based
98
124
  # on the format of the email.
99
125
  tmpl = opt[:tmpl] || opt[:template]
@@ -114,11 +140,11 @@ module Inkcite
114
140
 
115
141
  # First, collect all symbols in the natural order they are defined
116
142
  # in the email.
117
- footnotes = ctx.footnotes.select(&:symbol?)
143
+ footnotes = active_footnotes.select(&:symbol?)
118
144
 
119
145
  # Now add to the list all numeric footnotes ordered naturally
120
146
  # regardless of how they were ordered in the email.
121
- footnotes += ctx.footnotes.select(&:numeric?).sort { |f1, f2| f1.number <=> f2.number }
147
+ footnotes += active_footnotes.select(&:numeric?).sort { |f1, f2| f1.number <=> f2.number }
122
148
 
123
149
  html = ''
124
150
 
@@ -0,0 +1,79 @@
1
+ require 'litmus'
2
+
3
+ module Inkcite
4
+ module Renderer
5
+ class LitmusAnalytics < Base
6
+
7
+ def render tag, opt, ctx
8
+
9
+ # Litmus tracking is enabled only for production emails.
10
+ return nil unless ctx.production? && ctx.email?
11
+
12
+ # Deprecated code/id parameters. They shouldn't be passed anymore.
13
+ report_id = opt[:code] || opt[:id]
14
+ merge_tag = opt[MERGE_TAG] || ctx[MERGE_TAG]
15
+
16
+ # Initialize the Litmus API.
17
+ config = ctx.config[:litmus]
18
+ Litmus::Base.new(config[:subdomain], config[:username], config[:password], true)
19
+
20
+ # Will hold the Litmus Report object from which we'll retrieve the
21
+ # bug HTML to inject into the email.
22
+ report = nil
23
+
24
+ # If no code has been provided by the designer, check to see
25
+ # if one has been previously recorded for this version. If
26
+ # so, use it - otherwise, require one from litmus automatically.
27
+ if report_id.blank?
28
+
29
+ # Check to see if a campaign has been previously created for this
30
+ # version so the ID can be reused.
31
+ report_id = ctx.meta(:litmus_report_id)
32
+ if report_id.blank?
33
+
34
+ # Create a new report object using the title of the email specified
35
+ # in the helpers file.
36
+ report = Litmus::Report.create(ctx.title)
37
+
38
+ # Retrieve the unique ID assigned by Litmus and then stuff it
39
+ # into the meta data so we don't create a new one on future
40
+ # builds.
41
+ report_id = report['id']
42
+ ctx.set_meta :litmus_report_id, report_id
43
+
44
+ end
45
+
46
+ end
47
+
48
+ if report.nil?
49
+
50
+ report = Litmus::Report.show(report_id)
51
+ if report.nil?
52
+ ctx.error 'Invalid Litmus Analytics code or id', :code => report_id
53
+ return nil
54
+ end
55
+
56
+ end
57
+
58
+ # Grab the HTML from Litmus that needs to be injected into the source
59
+ # of the email.
60
+ bug_html = report[BUG_HTML]
61
+
62
+ # Replace the merge tag, if one was provided.
63
+ bug_html.gsub!('[UNIQUE]', merge_tag) unless merge_tag.nil?
64
+
65
+ # Inject HTML into the footer of the email where it won't be subject
66
+ # to inline'n or compression.
67
+ ctx.footer << bug_html
68
+
69
+ nil
70
+ end
71
+
72
+ private
73
+
74
+ BUG_HTML = 'bug_html'
75
+ MERGE_TAG = :'merge-tag'
76
+
77
+ end
78
+ end
79
+ end
@@ -21,34 +21,43 @@ module Inkcite
21
21
  # css isn't supported.
22
22
  element[:bgcolor] = hex(bgcolor) unless bgcolor.blank?
23
23
 
24
- # Assisted background image handling for maximum compatibility.
25
24
  bgimage = opt[:background]
26
25
  bgposition = opt[BACKGROUND_POSITION]
27
26
  bgrepeat = opt[BACKGROUND_REPEAT]
27
+ bgsize = opt[BACKGROUND_SIZE]
28
+
29
+ # Sets the background image attributes in the element's style
30
+ # attribute. These values take precedence on the desktop
31
+ # version of the email.
32
+ desktop_background = mix_background_shorthand(
33
+ bgcolor,
34
+ bgimage,
35
+ bgposition,
36
+ bgrepeat,
37
+ bgsize,
38
+ ctx
39
+ )
28
40
 
29
- # No need to set any CSS if there is no background image present on this
30
- # element. Previously, it would also set the background-color attribute
31
- # for unnecessary duplication.
32
- background_css(element.style, bgcolor, bgimage, bgposition, bgrepeat, nil, false, ctx) unless bgimage.blank?
33
-
34
- m_bgcolor = detect(opt[MOBILE_BACKGROUND_COLOR], opt[MOBILE_BGCOLOR])
35
- m_bgimage = detect(opt[MOBILE_BACKGROUND_IMAGE], opt[MOBILE_BACKGROUND])
41
+ element.style[:background] = desktop_background unless bgimage.blank?
36
42
 
37
- mobile_background = background_css(
38
- {},
39
- m_bgcolor,
40
- m_bgimage,
43
+ # Set the mobile background image attributes. These values take
44
+ # precedence on the mobile version of the email. If unset the
45
+ # mobile version inherits from the desktop version.
46
+ mobile_background = mix_background_shorthand(
47
+ detect(opt[MOBILE_BACKGROUND_COLOR], opt[MOBILE_BGCOLOR], bgcolor),
48
+ detect(opt[MOBILE_BACKGROUND_IMAGE], opt[MOBILE_BACKGROUND], bgimage),
41
49
  detect(opt[MOBILE_BACKGROUND_POSITION], bgposition),
42
50
  detect(opt[MOBILE_BACKGROUND_REPEAT], bgrepeat),
43
- detect(opt[MOBILE_BACKGROUND_SIZE]),
44
- (m_bgcolor && bgcolor) || (m_bgimage && bgimage),
51
+ detect(opt[MOBILE_BACKGROUND_SIZE], bgsize),
45
52
  ctx
46
53
  )
47
54
 
48
- unless mobile_background.blank?
55
+ unless mobile_background.blank? || mobile_background == desktop_background
56
+
57
+ mobile_background << ' !important' unless desktop_background.blank?
49
58
 
50
59
  # Add the responsive rule that applies to this element.
51
- rule = Rule.new(element.tag, unique_klass(ctx), mobile_background)
60
+ rule = Rule.new(element.tag, unique_klass(ctx), { :background => mobile_background })
52
61
 
53
62
  # Add the rule to the view and the element
54
63
  ctx.media_query << rule
@@ -87,61 +96,43 @@ module Inkcite
87
96
 
88
97
  private
89
98
 
90
- def background_css into, bgcolor, img, position, repeat, size, important, ctx
99
+ def mix_background_shorthand bgcolor, img, position, repeat, size, ctx
91
100
 
92
- unless bgcolor.blank? && img.blank?
101
+ values = []
93
102
 
94
- bgcolor = hex(bgcolor) unless bgcolor.blank?
103
+ values << hex(bgcolor) unless none?(bgcolor)
104
+
105
+ unless img.blank?
95
106
 
96
107
  # If no image has been provided or if the image provided is equal
97
108
  # to "none" then we'll set the values independently. Otherwise
98
109
  # we'll use a composite background declaration.
99
110
  if none?(img)
111
+ values << 'none'
100
112
 
101
- unless bgcolor.blank?
102
- bgcolor << ' !important' if important
103
- into[BACKGROUND_COLOR] = bgcolor
104
- end
113
+ else
105
114
 
106
- # Check specifically for a value of "none" which allows the email
107
- # designer to the background that is otherwise present on the
108
- # desktop version of the email.
109
- if img == NONE
110
- img = 'none'
111
- img << ' !important' if important
112
- into[BACKGROUND_IMAGE] = img
113
- end
115
+ values << "url(#{ctx.image_url(img)})"
114
116
 
115
- else
117
+ position = '0% 0%' if position.blank? && !size.blank?
118
+ unless position.blank?
119
+ values << position
120
+ unless size.blank?
121
+ values << '/'
122
+ values << (size == 'fill' ? '100% auto' : size)
123
+ end
124
+ end
116
125
 
117
126
  # Default to no-repeat if a position has been supplied or replace
118
127
  # 'none' as a convenience (cause none is easier to type than no-repeat).
119
128
  repeat = 'no-repeat' if (repeat.blank? && !position.blank?) || repeat == NONE
129
+ values << repeat unless repeat.blank?
120
130
 
121
- sty = []
122
- sty << bgcolor unless bgcolor.blank?
123
-
124
- ctx.assert_image_exists(img)
125
-
126
- sty << "url(#{ctx.image_url(img)})"
127
- sty << position unless position.blank?
128
- sty << repeat unless repeat.blank?
129
- sty << '!important' if important
130
-
131
- into[:background] = sty.join(' ')
132
-
133
- end
134
-
135
- # Background size needs to be set independently. Perhaps it can be
136
- # mixed into background: but I couldn't make it work.
137
- unless size.blank?
138
- into[BACKGROUND_SIZE] = size
139
- into[BACKGROUND_SIZE] << ' !important' if important
140
131
  end
141
132
 
142
133
  end
143
134
 
144
- into
135
+ values.blank?? nil : values.join(' ')
145
136
  end
146
137
 
147
138
  end
@@ -1,3 +1,3 @@
1
1
  module Inkcite
2
- VERSION = "1.2.0"
2
+ VERSION = "1.3.0"
3
3
  end
data/lib/inkcite/view.rb CHANGED
@@ -151,7 +151,32 @@ module Inkcite
151
151
  end
152
152
 
153
153
  def footnotes
154
- @footnotes ||= []
154
+
155
+ if @footnotes.nil?
156
+ @footnotes = []
157
+
158
+ # Preload the array of footnotes if they exist
159
+ footnotes_tsv_file = @email.project_file(FOOTNOTES_TSV_FILE)
160
+ if File.exists?(footnotes_tsv_file)
161
+ CSV.foreach(footnotes_tsv_file, { :col_sep => "\t" }) do |fn|
162
+
163
+ id = fn[0]
164
+ next if id.blank?
165
+
166
+ text = fn[2]
167
+ next if text.blank?
168
+
169
+ # Read the symbol and replace it with nil (so that one will be auto-generated)
170
+ symbol = fn[1]
171
+ symbol = nil if symbol.blank?
172
+
173
+ @footnotes << Renderer::Footnote::Instance.new(id, symbol, text, false)
174
+
175
+ end
176
+ end
177
+ end
178
+
179
+ @footnotes
155
180
  end
156
181
 
157
182
  def file_name ext=nil
@@ -347,10 +372,10 @@ module Inkcite
347
372
  # Render the body statement and apply the email's background color to it.
348
373
  bgcolor = Renderer.hex(self[BACKGROUND])
349
374
 
350
- # Intentially not setting the link colors because those should be entirely
375
+ # Intentionally not setting the link colors because those should be entirely
351
376
  # controlled by the styles and attributes of the links themselves. By not
352
377
  # setting it, links created sans-helper should be visually distinct.
353
- html << Renderer.render("<body bgcolor=\"#{bgcolor}\" style=\"background-color: #{bgcolor}; width: 100% !important; min-width: 100% !important; margin: 0; padding: 0; -webkit-text-size-adjust: none; -ms-text-size-adjust: none;\">", self)
378
+ html << Renderer.render("<body bgcolor=\"#{bgcolor}\" style=\"background-color: #{bgcolor}; width: 100% !important; min-width: 100% !important; margin: 0 !important; padding: 0; -webkit-text-size-adjust: none; -ms-text-size-adjust: none;\">", self)
354
379
 
355
380
  html << minified
356
381
 
@@ -522,6 +547,9 @@ module Inkcite
522
547
  # Tab-separated file containing links declarations.
523
548
  LINKS_TSV_FILE = 'links.tsv'
524
549
 
550
+ # Tab-separated file containing footnote declarations.
551
+ FOOTNOTES_TSV_FILE = 'footnotes.tsv'
552
+
525
553
  def assert_in_browser msg
526
554
  raise msg if email? && !development?
527
555
  end
@@ -716,6 +744,10 @@ module Inkcite
716
744
  # Ensure that telephone numbers are displayed using the same style as links.
717
745
  reset << "a[href^=tel] { color: #{self[Renderer::Base::LINK_COLOR]}; text-decoration:none;}"
718
746
 
747
+ # Remove extraneous left-margins on Android 4.4
748
+ # https://litmus.com/community/code/4194-why-is-email-not-centered-on-android-4-4#comment-5727
749
+ reset << 'div[style*="margin: 16px 0"] { margin:0 !important; }'
750
+
719
751
  end
720
752
 
721
753
  # Reset the font on every cell to the default family.
@@ -91,12 +91,12 @@ describe Inkcite::Renderer::Td do
91
91
 
92
92
  it 'can have a custom background color on mobile' do
93
93
  Inkcite::Renderer.render('{td mobile-bgcolor=#f09}', @view).must_equal('<td class="m1">')
94
- @view.media_query.find_by_klass('m1').to_css.must_equal('td[class~="m1"] { background-color:#ff0099 }')
94
+ @view.media_query.find_by_klass('m1').to_css.must_equal('td[class~="m1"] { background:#ff0099 }')
95
95
  end
96
96
 
97
97
  it 'can override background color on mobile' do
98
98
  Inkcite::Renderer.render('{td bgcolor=#f00 mobile-bgcolor=#00f}', @view).must_equal('<td bgcolor=#ff0000 class="m1">')
99
- @view.media_query.find_by_klass('m1').to_css.must_equal('td[class~="m1"] { background-color:#0000ff !important }')
99
+ @view.media_query.find_by_klass('m1').to_css.must_equal('td[class~="m1"] { background:#0000ff !important }')
100
100
  end
101
101
 
102
102
  it 'can have a background image' do
@@ -109,18 +109,18 @@ describe Inkcite::Renderer::Td do
109
109
  end
110
110
 
111
111
  it 'can override background image on mobile' do
112
- Inkcite::Renderer.render('{td background=floor.jpg background-position=bottom mobile-background-image=sky.jpg mobile-background-position=top}', @view).must_equal('<td class="m1" style="background:url(images/floor.jpg) bottom no-repeat">')
113
- @view.media_query.find_by_klass('m1').to_css.must_equal('td[class~="m1"] { background:url(images/sky.jpg) top no-repeat !important }')
112
+ 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 }')
114
114
  end
115
115
 
116
- it 'can disable background image on mobile' do
117
- Inkcite::Renderer.render('{td bgcolor=#f00 background=floor.jpg background-position=bottom mobile-bgcolor=#0f0 mobile-background-image=none}', @view).must_equal('<td bgcolor=#ff0000 class="m1" style="background:#ff0000 url(images/floor.jpg) bottom no-repeat">')
118
- @view.media_query.find_by_klass('m1').to_css.must_equal('td[class~="m1"] { background-color:#00ff00 !important;background-image:none !important }')
116
+ it 'can override background position on mobile' do
117
+ 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 }')
119
119
  end
120
120
 
121
- it 'inherits background position and repeat on mobile' do
122
- Inkcite::Renderer.render('{td background=floor.jpg background-position=bottom mobile-background-image=sky.jpg}', @view).must_equal('<td class="m1" style="background:url(images/floor.jpg) bottom no-repeat">')
123
- @view.media_query.find_by_klass('m1').to_css.must_equal('td[class~="m1"] { background:url(images/sky.jpg) bottom no-repeat !important }')
121
+ it 'can disable background image on mobile' do
122
+ 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 }')
124
124
  end
125
125
 
126
126
  end
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.2.0
4
+ version: 1.3.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: 2015-09-15 00:00:00.000000000 Z
11
+ date: 2015-10-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -267,7 +267,7 @@ files:
267
267
  - lib/inkcite/renderer/increment.rb
268
268
  - lib/inkcite/renderer/like.rb
269
269
  - lib/inkcite/renderer/link.rb
270
- - lib/inkcite/renderer/litmus.rb
270
+ - lib/inkcite/renderer/litmus_analytics.rb
271
271
  - lib/inkcite/renderer/lorem.rb
272
272
  - lib/inkcite/renderer/mobile_image.rb
273
273
  - lib/inkcite/renderer/mobile_style.rb
@@ -1,33 +0,0 @@
1
- module Inkcite
2
- module Renderer
3
- class Litmus < Base
4
-
5
- def render tag, opt, ctx
6
-
7
- # Litmus tracking is enabled only for production emails.
8
- return nil unless ctx.production? && ctx.email?
9
-
10
- code = opt[:code] || opt[:id]
11
- return nil if code.blank?
12
-
13
- merge_tag = opt[MERGE_TAG] || ctx[MERGE_TAG]
14
-
15
- ctx.styles << "@media print{#_t { background-image: url('https://#{code}.emltrk.com/#{code}?p&d=#{merge_tag}');}}"
16
- ctx.styles << "div.OutlookMessageHeader {background-image:url('https://#{code}.emltrk.com/#{code}?f&d=#{merge_tag}')}"
17
- ctx.styles << "table.moz-email-headers-table {background-image:url('https://#{code}.emltrk.com/#{code}?f&d=#{merge_tag}')}"
18
- ctx.styles << "blockquote #_t {background-image:url('https://#{code}.emltrk.com/#{code}?f&d=#{merge_tag}')}"
19
- ctx.styles << "#MailContainerBody #_t {background-image:url('https://#{code}.emltrk.com/#{code}?f&d=#{merge_tag}')}"
20
-
21
- ctx.footer << '<div id="_t"></div>'
22
- ctx.footer << "<img src=\"https://#{code}.emltrk.com/#{code}?d=#{merge_tag}\" width=1 height=1 border=0 />"
23
-
24
- nil
25
- end
26
-
27
- private
28
-
29
- MERGE_TAG = :'merge-tag'
30
-
31
- end
32
- end
33
- end