antwort 0.0.12 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +12 -0
  4. data/.ruby-version +1 -1
  5. data/CHANGELOG.md +28 -1
  6. data/README.md +1 -1
  7. data/antwort.gemspec +2 -2
  8. data/lib/antwort.rb +5 -4
  9. data/lib/antwort/builder/builder.rb +15 -24
  10. data/lib/antwort/builder/email.rb +47 -22
  11. data/lib/antwort/builder/flattener.rb +8 -9
  12. data/lib/antwort/builder/partial.rb +12 -11
  13. data/lib/antwort/builder/style.rb +26 -27
  14. data/lib/antwort/{builder.rb → builders.rb} +3 -3
  15. data/lib/antwort/cli.rb +0 -1
  16. data/lib/antwort/cli/cli.rb +42 -48
  17. data/lib/antwort/cli/send.rb +11 -14
  18. data/lib/antwort/cli/upload.rb +29 -28
  19. data/lib/antwort/core.rb +4 -0
  20. data/lib/antwort/email/build.rb +41 -0
  21. data/lib/antwort/email/collection.rb +41 -0
  22. data/lib/antwort/email/data.rb +27 -0
  23. data/lib/antwort/email/template.rb +88 -0
  24. data/lib/antwort/helpers/file_helper.rb +27 -0
  25. data/lib/antwort/{helpers.rb → helpers/helper.rb} +2 -2
  26. data/lib/antwort/helpers/logic_helper.rb +81 -0
  27. data/lib/antwort/helpers/markup_helper.rb +37 -0
  28. data/lib/antwort/{builder/helpers/sanitizers.rb → helpers/sanitizers_helper.rb} +2 -4
  29. data/lib/antwort/helpers/server_helper.rb +32 -0
  30. data/lib/antwort/{server.rb → server/server.rb} +26 -23
  31. data/{template/project → lib/antwort/server}/views/404.html.erb +1 -1
  32. data/{template/project → lib/antwort/server}/views/index.html.erb +4 -6
  33. data/{template/project → lib/antwort/server}/views/layout.erb +5 -5
  34. data/{template/project/views/markup/_button.html.erb → lib/antwort/server/views/markup/button.html.erb} +0 -0
  35. data/{template/project/views/markup/_image_tag.html.erb → lib/antwort/server/views/markup/image_tag.html.erb} +0 -0
  36. data/{template/project → lib/antwort/server}/views/server.erb +0 -0
  37. data/lib/antwort/version.rb +1 -1
  38. data/spec/builder/builder_spec.rb +17 -22
  39. data/spec/builder/email_spec.rb +11 -12
  40. data/spec/builder/flattener_spec.rb +20 -21
  41. data/spec/builder/helpers_logic_spec.rb +69 -73
  42. data/spec/builder/partial_spec.rb +42 -51
  43. data/spec/builder/style_spec.rb +25 -34
  44. data/spec/{cli_spec.rb → cli/cli_spec.rb} +8 -9
  45. data/spec/cli/send_spec.rb +80 -0
  46. data/spec/cli/upload_spec.rb +17 -9
  47. data/spec/email/build_spec.rb +13 -0
  48. data/spec/email/collection_spec.rb +56 -0
  49. data/spec/email/data_spec.rb +40 -0
  50. data/spec/email/template_spec.rb +116 -0
  51. data/spec/fixtures/assets/css/demo/include.scss +3 -0
  52. data/spec/fixtures/assets/css/demo/inline.scss +33 -0
  53. data/spec/fixtures/assets/css/no-images/include.scss +1 -0
  54. data/spec/fixtures/assets/css/no-images/inline.scss +2 -0
  55. data/spec/fixtures/assets/css/shared/_base.scss +64 -0
  56. data/spec/fixtures/assets/css/shared/_mixins.scss +25 -0
  57. data/spec/fixtures/assets/css/shared/_reset.scss +59 -0
  58. data/spec/fixtures/assets/css/shared/_vars.scss +12 -0
  59. data/spec/fixtures/assets/css/shared/include.scss +23 -0
  60. data/spec/fixtures/assets/css/shared/inline.scss +9 -0
  61. data/spec/fixtures/build/demo-20160101/demo.html +177 -0
  62. data/spec/fixtures/build/demo-20160101/source/demo.html +118 -0
  63. data/spec/fixtures/build/demo-20160101/source/include.css +58 -0
  64. data/spec/fixtures/build/demo-20160101/source/inline.css +83 -0
  65. data/spec/fixtures/build/demo-20160102/demo.html +177 -0
  66. data/spec/fixtures/build/demo-20160102/source/demo.html +118 -0
  67. data/spec/fixtures/build/demo-20160102/source/include.css +58 -0
  68. data/spec/fixtures/build/demo-20160102/source/inline.css +83 -0
  69. data/{template/project/data/.empty_directory → spec/fixtures/emails/1-demo/_bar.erb} +0 -0
  70. data/spec/fixtures/emails/1-demo/_foo.erb +0 -0
  71. data/spec/fixtures/emails/1-demo/index.html.erb +2 -2
  72. data/spec/fixtures/emails/4-custom-layout/index.html.erb +6 -0
  73. data/spec/fixtures/emails/4-custom-layout/layout.erb +5 -0
  74. data/spec/fixtures/emails/demo/index.html.erb +4 -0
  75. data/spec/fixtures/emails/no-images/index.html.erb +4 -0
  76. data/spec/fixtures/emails/shared/_foo.erb +0 -0
  77. data/spec/fixtures/{views → emails/shared}/layout.erb +0 -0
  78. data/spec/helpers/file_helper_spec.rb +30 -0
  79. data/spec/server/server_spec.rb +57 -0
  80. data/spec/spec_helper.rb +18 -7
  81. data/template/project/Gemfile.tt +1 -7
  82. metadata +92 -42
  83. data/lib/antwort/builder/helpers/logic.rb +0 -82
  84. data/lib/antwort/cli/helpers.rb +0 -44
  85. data/lib/antwort/server/helpers.rb +0 -67
  86. data/lib/antwort/server/markup.rb +0 -39
  87. data/spec/cli/helpers_spec.rb +0 -60
  88. data/spec/fixtures/build/demo-123456/build.html +0 -7
  89. data/spec/fixtures/build/demo-123457/build.html +0 -7
  90. data/spec/fixtures/build/demo-bar-123/build.html +0 -7
  91. data/spec/fixtures/views/404.html.erb +0 -1
  92. data/spec/fixtures/views/index.html.erb +0 -14
  93. data/spec/fixtures/views/server.erb +0 -5
  94. data/spec/server_spec.rb +0 -54
  95. data/template/project/.ruby-version +0 -1
  96. data/template/project/data/config.yml +0 -3
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe Antwort::EmailData do
4
+ let(:data) { Antwort::EmailData.new(name: '1-demo') }
5
+
6
+ describe 'on Initialization' do
7
+ it 'has a name attribute' do
8
+ expect(data.name).to eq('1-demo')
9
+ end
10
+
11
+ it 'has a data attribute' do
12
+ result = {
13
+ foo: [{ title: 'foo' }, { title: 'bar' }]
14
+ }
15
+ expect(data.data).to eq(result)
16
+ end
17
+
18
+ describe 'has a path attribute, which' do
19
+ it 'has /data appended' do
20
+ expect(data.path).to eq(fixtures_root + '/data')
21
+ end
22
+
23
+ it 'defaults to pwd/data' do
24
+ expect(Antwort::EmailData.new(name: 'foo').path).to eq("#{Dir.pwd}/data")
25
+ end
26
+ end
27
+
28
+ describe 'has a file, which' do
29
+ it 'can be set as param' do
30
+ a = Antwort::EmailData.new(file: '/usr/foo/bar.yml')
31
+ expect(a.file).to eq('/usr/foo/bar.yml')
32
+ end
33
+
34
+ it 'defaults to pwd/data' do
35
+ a = Antwort::EmailData.new(name: '1-demo')
36
+ expect(a.file).to eq("#{Dir.pwd}/data/1-demo.yml")
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ describe Antwort::EmailTemplate do
4
+ let(:demo) { Antwort::EmailTemplate.new('1-demo') }
5
+ let(:no_layout) { Antwort::EmailTemplate.new('2-no-layout') }
6
+ let(:no_title) { Antwort::EmailTemplate.new('3-no-title') }
7
+ let(:custom_layout) { Antwort::EmailTemplate.new('4-custom-layout') }
8
+ let(:no_images) { Antwort::EmailTemplate.new('no-images') }
9
+
10
+ describe 'Initialization' do
11
+ it 'has a the name' do
12
+ expect(demo.name).to eq('1-demo')
13
+ end
14
+
15
+ it 'has a the path' do
16
+ expect(demo.path).to eq('emails/1-demo')
17
+ end
18
+
19
+ it 'has a the index file' do
20
+ expect(demo.file).to eq('emails/1-demo/index.html.erb')
21
+ end
22
+ end
23
+
24
+ describe 'body attribute' do
25
+ context 'with YAML front matter' do
26
+ it 'ignores front matter' do
27
+ four = '<p>Email four has a custom layout.</p>'
28
+ expect(custom_layout.body).to eq(four)
29
+ end
30
+ end
31
+ context 'without YAML front matter' do
32
+ it 'receives file as body' do
33
+ three = '<h1>Hello Three</h1>'
34
+ expect(no_title.body).to eq(three)
35
+ end
36
+ end
37
+ end
38
+
39
+ describe 'title attribute' do
40
+ context 'with a title' do
41
+ it 'returns the title' do
42
+ expect(demo.title).to eq('Email One')
43
+ end
44
+ end
45
+
46
+ context 'without a title' do
47
+ it "defaults to 'Untitled'" do
48
+ expect(no_title.title).to eq('Untitled')
49
+ end
50
+ end
51
+ end
52
+
53
+ describe 'data attribute' do
54
+ context 'with a YAML file' do
55
+ it 'sets to YAML data' do
56
+ expect(demo.data[:foo].length).to eq(2)
57
+ expect(demo.data[:foo].first).to eq(title: 'foo')
58
+ expect(demo.data[:foo].last).to eq(title: 'bar')
59
+ end
60
+ end
61
+
62
+ context 'without a YAML file' do
63
+ it 'defaults to empty hash' do
64
+ expect(no_title.data).to eq({})
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "layout" do
70
+ it "defaults to :'emails/shared/layout'" do
71
+ expect(demo.layout).to eq(:'emails/shared/layout')
72
+ end
73
+
74
+ it 'can be a custom layout' do
75
+ expect(custom_layout.layout).to eq(:'emails/4-custom-layout/layout')
76
+ end
77
+
78
+ it 'can be false (i.e. has no layout)' do
79
+ expect(no_layout.layout).to be false
80
+ end
81
+ end
82
+
83
+ it 'has a url helper' do
84
+ expect(demo.url).to eq('/template/1-demo')
85
+ end
86
+
87
+ describe 'API' do
88
+ it '`#has_images?`' do
89
+ expect(demo.has_images?).to be true
90
+ expect(Antwort::EmailTemplate.new('shared').has_images?).to be true
91
+ expect(no_images.has_images?).to be false
92
+ end
93
+
94
+ it "`#images` lists all images in template's assets" do
95
+ expect(demo.images).to eq ['placeholder.png']
96
+ expect(Antwort::EmailTemplate.new('shared').images).to eq ['placeholder-grey.png', 'placeholder-white.png']
97
+ expect(Antwort::EmailTemplate.new('no-images').images).to eq []
98
+ end
99
+
100
+ it '`#image_path` returns path for an image' do
101
+ expect(demo.image_path('placeholder.png')).to eq 'assets/images/1-demo/placeholder.png'
102
+ expect(demo.image_path('does-not-exist.png')).to be nil
103
+ end
104
+
105
+ it '`#partials` lists all partials of the template' do
106
+ expect(demo.partials).to eq ['_bar.erb', '_foo.erb']
107
+ expect(no_layout.partials).to eq []
108
+ end
109
+
110
+ it '`#last_build`' do
111
+ demo2 = Antwort::EmailTemplate.new('demo')
112
+ expect(demo.last_build).to eq('1-demo-123')
113
+ expect(demo2.last_build).to eq('demo-20160102')
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,3 @@
1
+ // demo/include.scss
2
+
3
+ @import "../shared/include";
@@ -0,0 +1,33 @@
1
+ // demo/inline.scss
2
+
3
+ @import "../shared/inline";
4
+
5
+ // Use email specific stylesheets for custom code that isn't used elsewhere.
6
+ // This helps for overriding default styles.
7
+
8
+ code {
9
+ font-size: 14px;
10
+ line-height: 16px;
11
+ font-family: 'Courier New', Courier, monospace;
12
+ background-color: #eeeeee;
13
+ color: #333333;
14
+
15
+ display: inline-block;
16
+ padding: 0 4px;
17
+ vertical-align: middle;
18
+ }
19
+
20
+ .table {
21
+ td {
22
+ border: 1px solid #dddddd;
23
+ border-left-width: 0;
24
+ padding-top: 10px;
25
+ padding-bottom: 10px;
26
+ &:first-child {
27
+ border-left-width: 1px;
28
+ }
29
+ }
30
+ }
31
+
32
+ // Note: These layout styles may not work across all email clients.
33
+ // They are here for documentation purposes.
@@ -0,0 +1 @@
1
+ // no-images/include.scss
@@ -0,0 +1,2 @@
1
+ // no-images/inline.scss
2
+
@@ -0,0 +1,64 @@
1
+ // shared/based.scss
2
+
3
+ @import "_vars";
4
+ @import "_mixins";
5
+
6
+ body {
7
+ margin: 0;
8
+ padding: 0;
9
+ }
10
+
11
+ .container {
12
+ width: 600px;
13
+ max-width: 600px;
14
+ }
15
+
16
+ .container-padding {
17
+ padding-left: $gutter;
18
+ padding-right: $gutter;
19
+ }
20
+
21
+ .content {
22
+ background-color: #ffffff;
23
+ }
24
+
25
+ .title {
26
+ font-weight: bold;
27
+ font-size: 24px;
28
+ line-height: 28px;
29
+ font-family: $fontFamily;
30
+ }
31
+
32
+ .body-text {
33
+ font-size: 16px;
34
+ line-height: 20px;
35
+ font-family: $fontFamily;
36
+ }
37
+
38
+
39
+ //-- Buttons
40
+
41
+ .button {
42
+ td {
43
+ @include border-radius(3px);
44
+ background-color: $buttonBgColor;
45
+ }
46
+
47
+ a {
48
+ @include border-radius(3px);
49
+ @include font(bold, 14px, 20px);
50
+ text-decoration: none;
51
+ display: inline-block;
52
+ padding: 12px 18px;
53
+ border: 1px solid darken($buttonBgColor, 5%);
54
+ background-color: $buttonBgColor;
55
+ color: $buttonColor;
56
+ }
57
+
58
+ &.green {
59
+ td, a {
60
+ background-color: $greenBtnBgColor;
61
+ border-color: darken($greenBtnBgColor, 5%);
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,25 @@
1
+ //
2
+ // Mixins
3
+ // -------------------
4
+ // shared properties that we don't want to repeatedly define
5
+
6
+ @mixin padding($top: $gutter, $right: $gutter, $bottom: $gutter, $left: $gutter) {
7
+ padding-top: $top;
8
+ padding-right: $right;
9
+ padding-bottom: $bottom;
10
+ padding-left: $left;
11
+ }
12
+
13
+ @mixin border-radius($radius: 4px){
14
+ -webkit-border-radius: $radius;
15
+ -moz-border-radius: $radius;
16
+ border-radius: $radius;
17
+ }
18
+
19
+ @mixin font($weight: normal, $size: 14px, $line-height: 20px, $family: $fontFamily) {
20
+ font-weight: $weight;
21
+ font-size: $size;
22
+ line-height: $line-height;
23
+ font-family: $family;
24
+ }
25
+
@@ -0,0 +1,59 @@
1
+ //
2
+ // Common Email Resets
3
+ // -------------------
4
+ // This file contains common email resets to adjust for quirks
5
+ // across email clients. We've separated these definitions
6
+ // because you should never need to change this.
7
+
8
+
9
+ // General resets
10
+ body {
11
+ margin:0;
12
+ padding:0;
13
+ -ms-text-size-adjust:100%;
14
+ -webkit-text-size-adjust:100%;
15
+ }
16
+
17
+ table {
18
+ border-spacing: 0;
19
+ }
20
+
21
+ table td {
22
+ border-collapse:collapse;
23
+ }
24
+
25
+ // Normalize Outlook.com styles
26
+ .ExternalClass{
27
+ width:100%;
28
+ }
29
+
30
+ .ExternalClass,
31
+ .ExternalClass p,
32
+ .ExternalClass span,
33
+ .ExternalClass font,
34
+ .ExternalClass td,
35
+ .ExternalClass div{
36
+ line-height: 100%;
37
+ }
38
+
39
+ // Outermost container in Outlook.com
40
+ .ReadMsgBody {
41
+ width: 100%;
42
+ background-color: #ebebeb;
43
+ }
44
+
45
+ // Remove any extra Outlook Spacing
46
+ table{
47
+ mso-table-lspace: 0pt;
48
+ mso-table-rspace: 0pt;
49
+ }
50
+
51
+ // Weird image resizing in Outlook
52
+ img{
53
+ -ms-interpolation-mode:bicubic;
54
+ }
55
+
56
+ // Sometimes Yahoo turns text into ads/search links
57
+ .yshortcuts a {
58
+ border-bottom: none !important;
59
+ }
@@ -0,0 +1,12 @@
1
+
2
+ // Variables
3
+ // -------------------
4
+
5
+ $fontFamily: Helvetica, Arial, sans-serif;
6
+
7
+ $gutter: 20px;
8
+
9
+ $buttonBgColor: #2095F2;
10
+ $buttonColor: #ffffff;
11
+
12
+ $greenBtnBgColor: #8AC249;
@@ -0,0 +1,23 @@
1
+
2
+ // Included Styles
3
+ // ------------------------
4
+ // These styles will be included in the <head> of your email.
5
+ // Remember to use !important to override inlined styles.
6
+
7
+ @import "_vars";
8
+ @import "_mixins";
9
+ @import "_reset";
10
+
11
+ @media screen and (max-width: 600px) {
12
+ .container {
13
+ width: 100% !important;
14
+ max-width: 100% !important;
15
+ }
16
+ }
17
+
18
+ @media screen and (max-width: 400px) {
19
+ .container-padding {
20
+ padding-left: $gutter/2;
21
+ padding-right: $gutter/2;
22
+ }
23
+ }
@@ -0,0 +1,9 @@
1
+ @import "_vars";
2
+ @import "_mixins";
3
+ @import "_base";
4
+
5
+ // Yahoo <table align="center"> fix
6
+ table[align="center"] {
7
+ margin-left: auto;
8
+ margin-right: auto;
9
+ }
@@ -0,0 +1,177 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2
+ <html lang="en">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- So that mobile will display zoomed in -->
6
+ <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- enable media queries for windows phone 8 -->
7
+ <meta name="format-detection" content="telephone=no"> <!-- disable auto telephone linking in iOS -->
8
+ <title>Fixture Demo</title>
9
+ <style type="text/css">
10
+ body {
11
+ margin: 0;
12
+ padding: 0;
13
+ -ms-text-size-adjust: 100%;
14
+ -webkit-text-size-adjust: 100%;
15
+ }
16
+
17
+ table {
18
+ border-spacing: 0;
19
+ }
20
+
21
+ table td {
22
+ border-collapse: collapse;
23
+ }
24
+
25
+ .ExternalClass {
26
+ width: 100%;
27
+ }
28
+
29
+ .ExternalClass,
30
+ .ExternalClass p,
31
+ .ExternalClass span,
32
+ .ExternalClass font,
33
+ .ExternalClass td,
34
+ .ExternalClass div {
35
+ line-height: 100%;
36
+ }
37
+
38
+ .ReadMsgBody {
39
+ width: 100%;
40
+ background-color: #ebebeb;
41
+ }
42
+
43
+ table {
44
+ mso-table-lspace: 0pt;
45
+ mso-table-rspace: 0pt;
46
+ }
47
+
48
+ img {
49
+ -ms-interpolation-mode: bicubic;
50
+ }
51
+
52
+ .yshortcuts a {
53
+ border-bottom: none !important;
54
+ }
55
+
56
+ @media screen and (max-width: 600px) {
57
+ .container {
58
+ width: 100% !important;
59
+ max-width: 100% !important;
60
+ }
61
+ }
62
+ @media screen and (max-width: 400px) {
63
+ .container-padding {
64
+ padding-left: 10px;
65
+ padding-right: 10px;
66
+ }
67
+ }
68
+ </style>
69
+
70
+
71
+ </head>
72
+ <body leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" style="margin:0;padding:0">
73
+
74
+ <!-- 100% wrapper (grey background) -->
75
+ <table border="0" width="100%" height="100%" cellpadding="0" cellspacing="0">
76
+ <tr>
77
+ <td align="center" valign="top">
78
+
79
+ <br>
80
+
81
+ <!-- 600px container (white background) -->
82
+ <table border="0" width="600" cellpadding="0" cellspacing="0" class="container" style="width:600px;max-width:600px">
83
+ <tr>
84
+ <td class="content container-padding" style="padding-left:20px;padding-right:20px;background-color:#ffffff">
85
+ <br>
86
+
87
+ <div class="title" style="font-weight:bold;font-size:24px;line-height:28px;font-family:Helvetica, Arial, sans-serif">Using Antwort Generator</div>
88
+ <br>
89
+
90
+ <div class="body-text" style="font-size:16px;line-height:20px;font-family:Helvetica, Arial, sans-serif">
91
+ This is a demo email to get you started. The ID is 'demo', based on the file name.
92
+ <br><br>
93
+
94
+ Make sure your body text is always wrapped with a <code style="font-size:14px;line-height:16px;font-family:'Courier New', Courier, monospace;background-color:#eeeeee;color:#333333;display:inline-block;padding:0 4px;vertical-align:middle">.body-text</code> class, if not within a <code style="font-size:14px;line-height:16px;font-family:'Courier New', Courier, monospace;background-color:#eeeeee;color:#333333;display:inline-block;padding:0 4px;vertical-align:middle">td</code> then as least within a <code style="font-size:14px;line-height:16px;font-family:'Courier New', Courier, monospace;background-color:#eeeeee;color:#333333;display:inline-block;padding:0 4px;vertical-align:middle">div</code>.
95
+ <br><br>
96
+
97
+ <strong>Loading YAML Data</strong><br>
98
+ If you have a YAML file with the same name as your email-template name, for example a <code style="font-size:14px;line-height:16px;font-family:'Courier New', Courier, monospace;background-color:#eeeeee;color:#333333;display:inline-block;padding:0 4px;vertical-align:middle">demo.yml</code> for the <code style="font-size:14px;line-height:16px;font-family:'Courier New', Courier, monospace;background-color:#eeeeee;color:#333333;display:inline-block;padding:0 4px;vertical-align:middle">demo</code> email, you can load data like this:
99
+ <br><br>
100
+
101
+
102
+ • Peter<br>
103
+
104
+ • Paul<br>
105
+
106
+ • Mary<br>
107
+
108
+ <br><br>
109
+
110
+ <strong>Image Tag Helper</strong><br>
111
+
112
+ Adding images in email requires a lot of extra markup. To dry up the code, we have an <code style="font-size:14px;line-height:16px;font-family:'Courier New', Courier, monospace;background-color:#eeeeee;color:#333333;display:inline-block;padding:0 4px;vertical-align:middle">image_tag</code> helper, which you can use like this:<br>
113
+ <img src="/assets/shared/placeholder.png" border="0" alt="Placeholder" width="50" height="50" class="foo" hspace="0" vspace="0">
114
+ <br><br>
115
+
116
+
117
+ <strong>Button Helper</strong><br>
118
+ This is how you use the <code style="font-size:14px;line-height:16px;font-family:'Courier New', Courier, monospace;background-color:#eeeeee;color:#333333;display:inline-block;padding:0 4px;vertical-align:middle">button</code> helper:
119
+ <br><br>
120
+ <table border="0" cellspacing="0" cellpadding="0" class="button">
121
+ <tr>
122
+ <td align="center" style="-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;background-color:#2095F2"><a href="/" style="-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;font-weight:bold;font-size:14px;line-height:20px;font-family:Helvetica, Arial, sans-serif;text-decoration:none;display:inline-block;padding:12px 18px;border:1px solid #0e89eb;background-color:#2095F2;color:#ffffff"><!--[if mso]>&nbsp;<![endif]-->Default Button →<!--[if mso]>&nbsp;<![endif]--></a></td>
123
+ </tr>
124
+ </table>
125
+ <br>
126
+ <table border="0" cellspacing="0" cellpadding="0" class="button green">
127
+ <tr>
128
+ <td align="center" style="-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;background-color:#8AC249;border-color:#7db53d"><a href="/" style="-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;font-weight:bold;font-size:14px;line-height:20px;font-family:Helvetica, Arial, sans-serif;text-decoration:none;display:inline-block;padding:12px 18px;border:1px solid #0e89eb;background-color:#8AC249;color:#ffffff;border-color:#7db53d"><!--[if mso]>&nbsp;<![endif]-->A green button →<!--[if mso]>&nbsp;<![endif]--></a></td>
129
+ </tr>
130
+ </table>
131
+
132
+ <br><br>
133
+
134
+ To create additional button styles, make sure you add the appropriate CSS class definitions. See <code style="font-size:14px;line-height:16px;font-family:'Courier New', Courier, monospace;background-color:#eeeeee;color:#333333;display:inline-block;padding:0 4px;vertical-align:middle">_base.scss</code> for an example.
135
+ <br><br>
136
+ </div>
137
+
138
+
139
+ <div class="body-text" style="font-size:16px;line-height:20px;font-family:Helvetica, Arial, sans-serif">
140
+ <strong>Using Partials</strong>
141
+ <br><br>
142
+
143
+ You can use the <code style="font-size:14px;line-height:16px;font-family:'Courier New', Courier, monospace;background-color:#eeeeee;color:#333333;display:inline-block;padding:0 4px;vertical-align:middle">partial</code> helper to include external files. Note: partial filenames <em>must</em> begin with an underscore '_'. Use the optional <code style="font-size:14px;line-height:16px;font-family:'Courier New', Courier, monospace;background-color:#eeeeee;color:#333333;display:inline-block;padding:0 4px;vertical-align:middle">locals</code> attribute to pass data to the partial.
144
+ </div>
145
+ <br>
146
+
147
+ <table border="0" cellspacing="0" cellpadding="0" class="table">
148
+ <tr>
149
+
150
+ <td width="200" align="center" class="body-text" style="font-size:16px;line-height:20px;font-family:Helvetica, Arial, sans-serif;border:1px solid #dddddd;border-left-width:1px;padding-top:10px;padding-bottom:10px">
151
+ <em>Hello Peter</em><br>
152
+ </td>
153
+
154
+ <td width="200" align="center" class="body-text" style="font-size:16px;line-height:20px;font-family:Helvetica, Arial, sans-serif;border:1px solid #dddddd;border-left-width:0;padding-top:10px;padding-bottom:10px">
155
+ <em>Hello Paul</em><br>
156
+ </td>
157
+
158
+ <td width="200" align="center" class="body-text" style="font-size:16px;line-height:20px;font-family:Helvetica, Arial, sans-serif;border:1px solid #dddddd;border-left-width:0;padding-top:10px;padding-bottom:10px">
159
+ <em>Hello Mary</em><br>
160
+ </td>
161
+
162
+ </tr>
163
+ </table>
164
+ <br><br>
165
+
166
+ </td>
167
+ </tr>
168
+ </table>
169
+ <!--/600px container -->
170
+
171
+ </td>
172
+ </tr>
173
+ </table>
174
+ <!--/100% wrapper-->
175
+
176
+ </body>
177
+ </html>