inkcite 1.1.2 → 1.2.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: 182fcefd2da0130e3ae5239e44f335ddfbcf91bb
4
- data.tar.gz: 824f616001add49b5617caec3371b50d422c113d
3
+ metadata.gz: dff1fb6ce80d821e6c797a6c691e904ed6dfb60d
4
+ data.tar.gz: dcea60b5e3efe7edabc97186822e09e8cf43c8d5
5
5
  SHA512:
6
- metadata.gz: b1d9756a8f8f57101227f7bb7cda12c778dffeb62562435d655d177b6ac3ab396a97aa5bddc33864bd7c26539f942242a0f1a66c8cf75efac7b5af13ef90f87b
7
- data.tar.gz: 9fb13a190e39c1a7d2a16012ebaf60137d4565ed50fd703f363ec8e153632d4ddd335b4786ba4921268c4943204c44cc3dd6215135659147f578e21ab65c39d2
6
+ metadata.gz: 8b19819db8870689817a7947159c7d30ff14e7a237c485dd42d43443691da47f2af0573e34df9f1873cdb14c8a20b71516ff0a23e6b9abdf06eac3747fd7a315
7
+ data.tar.gz: 118adc599578c2d779d841ea78c8808a8a49334b084809e48eae9e6499e505d93218e5c5ab25026c7cf14b34ec930c39b4bc45401a928d3562eaed823f43aa80
data/README.md CHANGED
@@ -89,6 +89,11 @@ By default, this will create the production version of your email. This
89
89
  includes fully-qualified URLs for images, link tracking and tagging and a host
90
90
  of other preflight features.
91
91
 
92
+ ## Learn More
93
+
94
+ Documentation for Inkcite is generously hosted by the friendly folks at [Readme].
95
+ Get started here: https://inkcite.readme.io/
96
+
92
97
  ## Bug Reports
93
98
 
94
99
  Github Issues is used for managing bug reports and feature requests. If you
@@ -108,3 +113,4 @@ details.
108
113
  [Litmus]: http://litmus.com
109
114
  [rubyinstaller]: http://rubyinstaller.org/
110
115
  [LICENSE]: https://github.com/inkceptional/inkcite/blob/master/LICENSE
116
+ [Readme]: https://readme.io
@@ -1 +1 @@
1
- gem bump --version major --release
1
+ gem bump --version major --push --release
@@ -1 +1 @@
1
- gem bump --version minor --release
1
+ gem bump --version minor --push --release
@@ -1 +0,0 @@
1
- gem bump --version patch --release
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
29
29
  spec.add_dependency 'faker'
30
30
  spec.add_dependency 'litmus'
31
31
  spec.add_dependency 'mail'
32
+ spec.add_dependency 'mailgun-ruby'
32
33
  spec.add_dependency 'net-sftp'
33
34
  spec.add_dependency 'rack'
34
35
  spec.add_dependency 'rubyzip'
@@ -1,3 +1,4 @@
1
+ require 'csv'
1
2
  require 'erubis'
2
3
  require 'i18n'
3
4
  require 'set'
@@ -36,7 +36,9 @@ module Inkcite
36
36
 
37
37
  # Copy the main Inkcite project files
38
38
  FILES.each do |file|
39
- FileUtils.cp File.join(from_path, file), full_init_path
39
+ from_file = File.join(from_path, file)
40
+ next unless File.exists?(from_file)
41
+ FileUtils.cp(from_file, full_init_path)
40
42
  puts "Created #{File.join(path, file)}"
41
43
  end
42
44
 
@@ -19,7 +19,11 @@ module Inkcite
19
19
  nil
20
20
  end
21
21
 
22
+ puts
22
23
  puts "Inkcite #{Inkcite::VERSION} is starting up ..."
24
+ puts 'Documentation available at http://inkcite.readme.io'
25
+ puts 'Press CTRL-C to exit server mode'
26
+ puts
23
27
 
24
28
  begin
25
29
  @server = ::WEBrick::HTTPServer.new({
@@ -47,6 +51,7 @@ module Inkcite
47
51
 
48
52
  puts "Your email is being served at http://#{host}:#{port}"
49
53
  puts "Point your mobile device to http://#{ip}:#{port}" if ip
54
+ puts
50
55
 
51
56
  @server.start
52
57
 
@@ -23,7 +23,7 @@ module Inkcite
23
23
  end
24
24
 
25
25
  def config
26
- Util.read_yml(File.join(path, 'config.yml'), true)
26
+ Util.read_yml(File.join(path, 'config.yml'), :fail_if_not_exists => true)
27
27
  end
28
28
 
29
29
  def formats env
@@ -139,7 +139,7 @@ module Inkcite
139
139
  META_FILE = '.inkcite'
140
140
 
141
141
  def meta_data
142
- Util.read_yml(File.join(path, meta_file_name), false)
142
+ Util.read_yml(File.join(path, meta_file_name))
143
143
  end
144
144
 
145
145
  def meta_file_name
@@ -1,4 +1,5 @@
1
1
  require 'mail'
2
+ require 'mailgun'
2
3
 
3
4
  module Inkcite
4
5
  class Mailer
@@ -27,11 +28,11 @@ module Inkcite
27
28
  cc = recipients[:internal]
28
29
 
29
30
  self.send(email, {
30
- :to => to,
31
- :cc => cc,
32
- :bcc => true,
33
- :tag => "Preview ##{count}"
34
- })
31
+ :to => to,
32
+ :cc => cc,
33
+ :bcc => true,
34
+ :tag => "Preview ##{count}"
35
+ })
35
36
 
36
37
  end
37
38
 
@@ -40,8 +41,8 @@ module Inkcite
40
41
  count = increment(email, :developer)
41
42
 
42
43
  self.send(email, {
43
- :tag => "Developer Test ##{count}"
44
- })
44
+ :tag => "Developer Test ##{count}"
45
+ })
45
46
 
46
47
  end
47
48
 
@@ -57,10 +58,10 @@ module Inkcite
57
58
  count = increment(email, :internal)
58
59
 
59
60
  self.send(email, {
60
- :to => recipients[:internal],
61
- :bcc => true,
62
- :tag => "Internal Proof ##{count}"
63
- })
61
+ :to => recipients[:internal],
62
+ :bcc => true,
63
+ :tag => "Internal Proof ##{count}"
64
+ })
64
65
 
65
66
  end
66
67
 
@@ -87,46 +88,82 @@ module Inkcite
87
88
 
88
89
  def self.send_version email, version, opt
89
90
 
90
- config = email.config[:smtp]
91
+ # The version of the email we will be sending.
92
+ view = email.view(:preview, :email, version)
93
+
94
+ # Subject line tag such as "Preview #3"
95
+ tag = opt[:tag]
96
+
97
+ subject = view.subject
98
+ subject = "#{subject} (#{tag})" unless tag.blank?
99
+
100
+ if config = email.config[:mailgun]
101
+ send_version_via_mailgun config, view, subject, opt
102
+ elsif config = email.config[:smtp]
103
+ send_version_via_smtp config, view, subject, opt
104
+ else
105
+ puts 'Unable to send previews. Please configure mailgun or smtp sections in config.yml'
106
+ end
107
+
108
+ end
109
+
110
+ private
111
+
112
+ def self.send_version_via_mailgun config, view, subject, opt
113
+
114
+ # The address of the developer
115
+ from = config[:from]
116
+
117
+ # First, instantiate the Mailgun Client with your API key
118
+ mg_client = Mailgun::Client.new config[:'api-key']
119
+
120
+ # Define your message parameters
121
+ message_params = {
122
+ :from => from,
123
+ :to => opt[:to] || from,
124
+ :subject => subject,
125
+ :html => view.render!
126
+ }
127
+
128
+ message_params[:cc] = opt[:cc] unless opt[:cc].blank?
129
+ message_params[:bcc] = from if opt[:bcc] == true
130
+
131
+ # Send your message through the client
132
+ mg_client.send_message config[:domain], message_params
133
+
134
+ end
135
+
136
+ def self.send_version_via_smtp config, view, _subject, opt
91
137
 
92
138
  Mail.defaults do
93
139
  delivery_method :smtp, {
94
- :address => config[:host],
95
- :port => config[:port],
96
- :user_name => config[:username],
97
- :password => config[:password],
98
- :authentication => :plain,
99
- :enable_starttls_auto => true
100
- }
140
+ :address => config[:host],
141
+ :port => config[:port],
142
+ :user_name => config[:username],
143
+ :password => config[:password],
144
+ :authentication => :plain,
145
+ :enable_starttls_auto => true
146
+ }
101
147
  end
102
148
 
103
149
  # The address of the developer
104
150
  _from = config[:from]
105
151
 
106
- # Subject line tag such as "Preview #3"
107
- _tag = opt[:tag]
108
-
109
152
  # True if the developer should be bcc'd.
110
153
  _bcc = opt[:bcc] == true
111
154
 
112
- # The version of the email we will be sending.
113
- _view = email.view(:preview, :email, version)
114
-
115
- _subject = _view.subject
116
- _subject = "#{_subject} (#{_tag})" unless _tag.blank?
117
-
118
155
  mail = Mail.new do
119
156
 
120
- to opt[:to] || _from
121
- cc opt[:cc]
122
- from _from
157
+ to opt[:to] || _from
158
+ cc opt[:cc]
159
+ from _from
123
160
  subject _subject
124
161
 
125
162
  bcc(_from) if _bcc
126
163
 
127
164
  html_part do
128
165
  content_type 'text/html; charset=UTF-8'
129
- body _view.render!
166
+ body view.render!
130
167
  end
131
168
 
132
169
  end
@@ -44,6 +44,7 @@ module Inkcite
44
44
  packed_line = ''
45
45
  end
46
46
 
47
+ packed_line << ' ' unless packed_line.blank?
47
48
  packed_line << line
48
49
 
49
50
  end
@@ -10,6 +10,7 @@ require_relative 'renderer/footnote'
10
10
  require_relative 'renderer/google_analytics'
11
11
  require_relative 'renderer/image'
12
12
  require_relative 'renderer/in_browser'
13
+ require_relative 'renderer/increment'
13
14
  require_relative 'renderer/like'
14
15
  require_relative 'renderer/link'
15
16
  require_relative 'renderer/litmus'
@@ -149,6 +150,7 @@ module Inkcite
149
150
 
150
151
  # Dynamic renderers for custom behavior and tags.
151
152
  @renderers ||= {
153
+ :'++' => Increment.new,
152
154
  :a => Link.new,
153
155
  :button => Button.new,
154
156
  :div => Div.new,
@@ -3,41 +3,48 @@ module Inkcite
3
3
  class Base
4
4
 
5
5
  # Constants for style and property names with dashes in them.
6
- BACKGROUND_COLOR = :'background-color'
7
- BACKGROUND_IMAGE = :'background-image'
8
- BACKGROUND_REPEAT = :'background-repeat'
6
+ BACKGROUND_COLOR = :'background-color'
7
+ BACKGROUND_IMAGE = :'background-image'
8
+ BACKGROUND_REPEAT = :'background-repeat'
9
9
  BACKGROUND_POSITION = :'background-position'
10
- BACKGROUND_SIZE = :'background-size'
11
- BORDER_BOTTOM = :'border-bottom'
12
- BORDER_COLLAPSE = :'border-collapse'
13
- BORDER_RADIUS = :'border-radius'
14
- BORDER_SPACING = :'border-spacing'
15
- BOX_SHADOW = :'box-shadow'
16
- FONT_FAMILY = :'font-family'
17
- FONT_SIZE = :'font-size'
18
- FONT_WEIGHT = :'font-weight'
19
- LETTER_SPACING = :'letter-spacing'
20
- LINE_HEIGHT = :'line-height'
21
- LINK_COLOR = :'#link'
22
- MARGIN_TOP = :'margin-top'
23
- PADDING_X = :'padding-x'
24
- PADDING_Y = :'padding-y'
25
- TEXT_ALIGN = :'text-align'
26
- TEXT_DECORATION = :'text-decoration'
27
- TEXT_SHADOW = :'text-shadow'
28
- TEXT_SHADOW_BLUR = :'shadow-blur'
29
- TEXT_SHADOW_OFFSET = :'shadow-offset'
30
- VERTICAL_ALIGN = :'vertical-align'
10
+ BACKGROUND_SIZE = :'background-size'
11
+ BORDER_BOTTOM = :'border-bottom'
12
+ BORDER_COLLAPSE = :'border-collapse'
13
+ BORDER_RADIUS = :'border-radius'
14
+ BORDER_SPACING = :'border-spacing'
15
+ BOX_SHADOW = :'box-shadow'
16
+ FONT_FAMILY = :'font-family'
17
+ FONT_SIZE = :'font-size'
18
+ FONT_WEIGHT = :'font-weight'
19
+ LETTER_SPACING = :'letter-spacing'
20
+ LINE_HEIGHT = :'line-height'
21
+ LINK_COLOR = :'#link'
22
+ MARGIN = :'margin'
23
+ MARGIN_BOTTOM = :'margin-bottom'
24
+ MARGIN_LEFT = :'margin-left'
25
+ MARGIN_RIGHT = :'margin-right'
26
+ MARGIN_TOP = :'margin-top'
27
+ PADDING_X = :'padding-x'
28
+ PADDING_Y = :'padding-y'
29
+ TEXT_ALIGN = :'text-align'
30
+ TEXT_DECORATION = :'text-decoration'
31
+ TEXT_SHADOW = :'text-shadow'
32
+ TEXT_SHADOW_BLUR = :'shadow-blur'
33
+ TEXT_SHADOW_OFFSET = :'shadow-offset'
34
+ VERTICAL_ALIGN = :'vertical-align'
35
+
36
+ # CSS Margins
37
+ MARGINS = [MARGIN_TOP, MARGIN_LEFT, MARGIN_BOTTOM, MARGIN_RIGHT]
31
38
 
32
39
  # CSS Directions
33
- DIRECTIONS = [ :top, :right, :bottom, :left ]
40
+ DIRECTIONS = [:top, :right, :bottom, :left]
34
41
 
35
42
  # Attribute and CSS dimensions
36
- DIMENSIONS = [ :width, :height ]
43
+ DIMENSIONS = [:width, :height]
37
44
 
38
45
  # Common value declarations
39
46
  POUND_SIGN = '#'
40
- NONE = 'none'
47
+ NONE = 'none'
41
48
 
42
49
  # Zero-width space character
43
50
  ZERO_WIDTH_SPACE = '&#8203;'
@@ -122,6 +129,24 @@ module Inkcite
122
129
  font
123
130
  end
124
131
 
132
+ def mix_margins element, opt, ctx
133
+
134
+ # Check to see if the 'all' margin attribute is specified.
135
+ all_margin = opt[MARGIN]
136
+
137
+ # Applying individual margins helps ensure compatibility across
138
+ # all email clients. Cough! Cough! Looking at you Outlook.
139
+ MARGINS.each do |margin|
140
+
141
+ # Check for specific direction margin (e.g. margin-left) which
142
+ # would override all margins. Otherwise, inherit all margin.
143
+ amt = (opt[margin] || all_margin).to_i
144
+ element.style[margin] = px(amt) if amt > 0
145
+
146
+ end
147
+
148
+ end
149
+
125
150
  def mix_text_shadow element, opt, ctx
126
151
 
127
152
  shadow = detect(opt[:shadow], opt[TEXT_SHADOW])
@@ -0,0 +1,21 @@
1
+ module Inkcite
2
+ module Renderer
3
+ class Increment < Base
4
+
5
+ def render tag, opt, ctx
6
+
7
+ # Get the unique ID for which a counter will be incremented.
8
+ # Or use the default value.
9
+ id = opt[:id] || DEFAULT
10
+ ctx.unique_id(id).to_s
11
+
12
+ end
13
+
14
+ private
15
+
16
+ # Tip o' the hat to the most-used index variable name.
17
+ DEFAULT = 'i'
18
+
19
+ end
20
+ end
21
+ end
@@ -42,6 +42,10 @@ module Inkcite
42
42
  id = opt[:id]
43
43
  href = opt[:href]
44
44
 
45
+ # If a URL wasn't provided in the HTML, then check to see if there is
46
+ # a link declared in the project's links_tsv file.
47
+ href = ctx.links_tsv[id] if href.blank?
48
+
45
49
  # True if the href is missing. If so, we may try to look it up by it's ID
46
50
  # or we'll insert a default TBD link.
47
51
  missing = href.blank?
@@ -10,6 +10,33 @@ module Inkcite
10
10
  return nil
11
11
  end
12
12
 
13
+ # True if this is a opening tag - e.g. {feature ...}, not {/feature}
14
+ is_open_tag = !tag.starts_with?(SLASH)
15
+
16
+ # When a custom opening tag is encountered, if there is a corresponding
17
+ # closing tag, we'll save the options provided at open so that they
18
+ # can be pop'd by the closing tag and used in the closing HTML.
19
+ if is_open_tag
20
+
21
+ # Verify that a closing tag has been defined and push the opts
22
+ # onto the stack. No need to push opts and pollute the stack if
23
+ # there is no closing tag to take advantage of them.
24
+ close_tag = "#{SLASH}#{tag}"
25
+ ctx.tag_stack(tag) << opt unless ctx[close_tag].blank?
26
+
27
+ else
28
+
29
+ # Chop off the forward slash to reveal the original open tag. Then
30
+ # grab the tag stack for said open tag. Pop the most recently provided
31
+ # opts off the stack so those values are available again.
32
+ open_tag = tag[1..-1]
33
+ tag_stack = ctx.tag_stack(open_tag)
34
+
35
+ # The provided opts take precedence over the ones passed to the open tag.
36
+ opt = tag_stack.pop.merge(opt) if tag_stack
37
+
38
+ end
39
+
13
40
  # Need to clone the property - otherwise, we modify the original property.
14
41
  # Which is bad.
15
42
  html = html.clone
@@ -33,6 +60,7 @@ module Inkcite
33
60
 
34
61
  DOLLAR = '$'
35
62
  EQUALS = '='
63
+ SLASH = '/'
36
64
 
37
65
  end
38
66
  end
@@ -41,8 +41,8 @@ module Inkcite
41
41
  border_collapse = opt[BORDER_COLLAPSE]
42
42
  table.style[BORDER_COLLAPSE] = border_collapse unless border_collapse.blank?
43
43
 
44
- margin_top = opt[MARGIN_TOP].to_i
45
- table.style[MARGIN_TOP] = px(margin_top) if margin_top > 0
44
+ # Apply margins.
45
+ mix_margins table, opt, ctx
46
46
 
47
47
  mobile = opt[:mobile]
48
48
 
@@ -55,11 +55,13 @@ module Inkcite
55
55
  end
56
56
  end
57
57
 
58
- def self.read_yml file, fail_if_not_exists=false
58
+ def self.read_yml file, opts={}
59
59
  if File.exist?(file)
60
- symbolize_keys(YAML.load_file(file))
61
- elsif fail_if_not_exists
62
- raise "File not found: #{file}" if fail_if_not_exists
60
+ yml = YAML.load_file(file)
61
+ symbolize_keys(yml) unless opts[:symbolize_keys] == false
62
+ yml
63
+ elsif opts[:fail_if_not_exists]
64
+ raise "File not found: #{file}"
63
65
  else
64
66
  {}
65
67
  end
@@ -1,3 +1,3 @@
1
1
  module Inkcite
2
- VERSION = "1.1.2"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -239,6 +239,22 @@ module Inkcite
239
239
  @links ||= {}
240
240
  end
241
241
 
242
+ # Returns a hash of the links.tsv file from the project which is used
243
+ # to populate the {a} and {button} hrefs when an href isn't defined.
244
+ def links_tsv
245
+ @links_tsv ||= begin
246
+ links_tsv_file = @email.project_file(LINKS_TSV_FILE)
247
+ if File.exists?(links_tsv_file)
248
+ Hash[CSV.read(links_tsv_file, { :col_sep => "\t" })]
249
+ else
250
+ {}
251
+ end
252
+ rescue Exception => e
253
+ error("There was a problem reading #{LINKS_TSV_FILE}: #{e.message}")
254
+ {}
255
+ end
256
+ end
257
+
242
258
  def meta key
243
259
  md = meta_data
244
260
  md.nil?? nil : md[key]
@@ -451,8 +467,6 @@ module Inkcite
451
467
  def write_links_csv out
452
468
 
453
469
  unless @links.blank?
454
-
455
- require 'csv'
456
470
  csv = CSV.new(out, :force_quotes => true)
457
471
 
458
472
  # Write each link to the CSV file.
@@ -501,6 +515,12 @@ module Inkcite
501
515
  # Used to mark a helper.tsv line as a comment.
502
516
  COMMENT = '//'
503
517
 
518
+ # Name of the local font cache file used for local storage of
519
+ # Google Font CSS
520
+ FONT_CACHE_FILE = '.inkcite_fonts'
521
+
522
+ # Tab-separated file containing links declarations.
523
+ LINKS_TSV_FILE = 'links.tsv'
504
524
 
505
525
  def assert_in_browser msg
506
526
  raise msg if email? && !development?
@@ -591,6 +611,54 @@ module Inkcite
591
611
  html
592
612
  end
593
613
 
614
+ def inline_google_fonts
615
+
616
+ reset = ''
617
+
618
+ # Google Web Fonts support courtesy of
619
+ # http://www.emaildesignreview.com/html-email-coding/web-fonts-in-email-1482/
620
+ font_urls = self[:fonts]
621
+ unless font_urls.blank?
622
+ require 'open-uri'
623
+
624
+ # Load the previously cached font, if any
625
+ font_cache_path = @email.project_file(FONT_CACHE_FILE)
626
+ font_cache = Util.read_yml(font_cache_path, :symbolize_keys => false)
627
+
628
+ # True if the cache needs to be updated because a new URL was
629
+ # added to it.
630
+ updated = false
631
+
632
+ # If you use @font-face in HTML email, Outlook 07/10/13 will default all
633
+ # text back to Times New Roman.
634
+ # http://www.emaildesignreview.com/html-email-coding/web-fonts-in-email-1482/
635
+ reset << '@media screen {'
636
+
637
+ # Iterate through the configured fonts. Check to see if we've already cached
638
+ # Google's response. If not, retrieve it and add it to the
639
+ font_urls.each do |url|
640
+ if font_cache[url].blank?
641
+ begin
642
+ font_cache[url] = open(url).read
643
+ updated = true
644
+ rescue
645
+ error 'Unable to load Google Web Font', { :url => url }
646
+ end
647
+ end
648
+
649
+ reset << font_cache[url]
650
+ end
651
+ reset << '}'
652
+
653
+ # If the fontcache was updated, update it in our sekret file.
654
+ File.write(font_cache_path, font_cache.to_yaml) if updated
655
+
656
+ end
657
+
658
+ reset
659
+ end
660
+
661
+
594
662
  def inline_scripts
595
663
 
596
664
  code = ''
@@ -659,29 +727,7 @@ module Inkcite
659
727
  reset << 'o\:* { behavior: url(#default#VML); display: inline-block; }'
660
728
  end
661
729
 
662
- # Google Web Fonts support courtesy of
663
- # http://www.emaildesignreview.com/html-email-coding/web-fonts-in-email-1482/
664
- font_urls = self[:fonts]
665
- unless font_urls.blank?
666
- require 'open-uri'
667
-
668
- # If you use @font-face in HTML email, Outlook 07/10/13 will default all
669
- # text back to Times New Roman.
670
- # http://www.emaildesignreview.com/html-email-coding/web-fonts-in-email-1482/
671
- reset << "@media screen {"
672
-
673
- # Iterate through the configured fonts and
674
- font_urls.each do |url|
675
- begin
676
- reset << open(url).read
677
- rescue
678
- error "Unable to load Google Web Font", { :url => url }
679
- end
680
-
681
- end
682
- reset << "}"
683
-
684
- end
730
+ reset << inline_google_fonts
685
731
 
686
732
  # Responsive styles.
687
733
  reset += @media_query.to_a unless @media_query.blank?
@@ -0,0 +1,20 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/autorun'
3
+ require 'inkcite'
4
+
5
+ describe Inkcite::View do
6
+
7
+ before do
8
+ @view = Inkcite::Email.new('test/project/').view(:production, :email)
9
+ @view.is_enabled?(:minify).must_equal(true)
10
+ end
11
+
12
+ it "won't create compound words out of line breaks" do
13
+ Inkcite::Minifier.html(%w(I am a multi-line string.), @view).must_equal('I am a multi-line string.')
14
+ end
15
+
16
+ it "removes trailing line-breaks" do
17
+ Inkcite::Minifier.html(["This string has trailing line-breaks.\n\r\f"], @view).must_equal('This string has trailing line-breaks.')
18
+ end
19
+
20
+ end
@@ -0,0 +1,34 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/autorun'
3
+ require 'inkcite'
4
+
5
+ describe Inkcite::Renderer::Table do
6
+
7
+ before do
8
+ @view = Inkcite::Email.new('test/project/').view(:development, :email)
9
+ end
10
+
11
+ it 'defaults border, cellpadding and cellspacing to zero' do
12
+ Inkcite::Renderer.render('{table}{/table}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0><tr></tr></table>')
13
+ end
14
+
15
+ it 'supports custom margins in px' do
16
+ Inkcite::Renderer.render('{table margin-top=15}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="margin-top:15px"><tr>')
17
+ Inkcite::Renderer.render('{table margin-left=16}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="margin-left:16px"><tr>')
18
+ Inkcite::Renderer.render('{table margin-bottom=17}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="margin-bottom:17px"><tr>')
19
+ Inkcite::Renderer.render('{table margin-right=18}', @view).must_equal('<table border=0 cellpadding=0 cellspacing=0 style="margin-right:18px"><tr>')
20
+ end
21
+
22
+ it 'supports multiple custom margins in px' do
23
+ 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>')
24
+ end
25
+
26
+ it 'supports a single all margin attribute' do
27
+ 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>')
28
+ end
29
+
30
+ it 'supports unified margins with directional override' do
31
+ 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>')
32
+ end
33
+
34
+ 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.1.2
4
+ version: 1.2.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-07-08 00:00:00.000000000 Z
11
+ date: 2015-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - '>='
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: mailgun-ruby
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: net-sftp
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -250,6 +264,7 @@ files:
250
264
  - lib/inkcite/renderer/image.rb
251
265
  - lib/inkcite/renderer/image_base.rb
252
266
  - lib/inkcite/renderer/in_browser.rb
267
+ - lib/inkcite/renderer/increment.rb
253
268
  - lib/inkcite/renderer/like.rb
254
269
  - lib/inkcite/renderer/link.rb
255
270
  - lib/inkcite/renderer/litmus.rb
@@ -274,6 +289,7 @@ files:
274
289
  - lib/inkcite/view/media_query.rb
275
290
  - lib/inkcite/view/tag_stack.rb
276
291
  - test/email_spec.rb
292
+ - test/minifier_spec.rb
277
293
  - test/parser_spec.rb
278
294
  - test/project/config.yml
279
295
  - test/project/helpers.tsv
@@ -288,6 +304,7 @@ files:
288
304
  - test/renderer/link_spec.rb
289
305
  - test/renderer/mobile_image_spec.rb
290
306
  - test/renderer/mobile_style_spec.rb
307
+ - test/renderer/table_spec.rb
291
308
  - test/renderer/td_spec.rb
292
309
  - test/renderer_spec.rb
293
310
  - test/view_spec.rb
@@ -317,6 +334,7 @@ specification_version: 4
317
334
  summary: Simplifying email development
318
335
  test_files:
319
336
  - test/email_spec.rb
337
+ - test/minifier_spec.rb
320
338
  - test/parser_spec.rb
321
339
  - test/project/config.yml
322
340
  - test/project/helpers.tsv
@@ -331,6 +349,7 @@ test_files:
331
349
  - test/renderer/link_spec.rb
332
350
  - test/renderer/mobile_image_spec.rb
333
351
  - test/renderer/mobile_style_spec.rb
352
+ - test/renderer/table_spec.rb
334
353
  - test/renderer/td_spec.rb
335
354
  - test/renderer_spec.rb
336
355
  - test/view_spec.rb