soryo 0.0.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.
@@ -0,0 +1,25 @@
1
+ require 'mail'
2
+ require 'tempfile'
3
+ require 'launchy'
4
+
5
+ module Soryo
6
+ class BrowserTester < Soryo::Tester
7
+
8
+ attr_reader :preview_obj
9
+ def run(email, options)
10
+ file = Tempfile.new(['tempemail', '.html'])
11
+ file << email
12
+ file.close
13
+ `open #{file.path}`
14
+ end
15
+
16
+ def self.tester_name
17
+ 'preview'
18
+ end
19
+
20
+ def initialize
21
+ end
22
+
23
+ end
24
+ end
25
+
@@ -0,0 +1,24 @@
1
+ module Soryo
2
+ class Tester
3
+
4
+ def self.descendants
5
+ descendants = []
6
+ ObjectSpace.each_object(singleton_class) do |k|
7
+ descendants.unshift k unless k == self
8
+ end
9
+ descendants
10
+ end
11
+
12
+ def initialize
13
+ end
14
+
15
+ def tester_name
16
+ abort('Tester.tester_name should not be run directly')
17
+ end
18
+
19
+ def run(email, options)
20
+ abort('Tester.run should not be called directly')
21
+ end
22
+
23
+ end
24
+ end
data/soryo.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "soryo"
5
+ spec.version = "0.0.0"
6
+ spec.authors = ["Alex Stephen"]
7
+ spec.email = ["stepa@umich.edu"]
8
+ spec.description = %q{Let's build all the emails!}
9
+ spec.summary = %q{EMAILS! EMAILS! EMAILS!}
10
+ spec.homepage = "http://www.soryorb.com"
11
+ spec.license = "MIT"
12
+
13
+ spec.files = `git ls-files`.split($/)
14
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
15
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
+ spec.require_paths = ["lib"]
17
+
18
+ spec.add_development_dependency 'bundler', '~> 1.3'
19
+ spec.add_development_dependency 'rake'
20
+ spec.add_development_dependency 'rspec'
21
+
22
+ spec.add_runtime_dependency 'mercenary'
23
+ spec.add_runtime_dependency 'premailer'
24
+ spec.add_runtime_dependency 'liquid'
25
+ spec.add_runtime_dependency 'mail'
26
+ spec.add_runtime_dependency 'launchy'
27
+
28
+ end
@@ -0,0 +1,31 @@
1
+ require_relative '../lib/soryo.rb'
2
+
3
+ describe Soryo::Command do
4
+ before :each do
5
+ @command = Soryo::Command.new(nil)
6
+ end
7
+ describe '#new' do
8
+ it 'should be of type Command' do
9
+ expect(@command).to be_an_instance_of Soryo::Command
10
+ end
11
+
12
+ it 'should have a config attribute of type Config' do
13
+ expect(@command.config).to be_an_instance_of Soryo::Config
14
+ end
15
+
16
+ it 'should not alter config hash if nil passed in' do
17
+ expect(@command.config).to eq(Soryo::DEFAULTS)
18
+ end
19
+
20
+ it 'should merge in options hash if passed in' do
21
+ options = Hash['test' => 20, 'config_test' => true]
22
+ merged_hash = Soryo::DEFAULTS.merge(options)
23
+ config2 = Soryo::Command.new(options)
24
+ expect(config2.config).to eq(merged_hash)
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+
@@ -0,0 +1,47 @@
1
+ require_relative '../lib/soryo.rb'
2
+
3
+ require 'yaml'
4
+
5
+ describe Soryo::Config do
6
+ before :each do
7
+ @config = Soryo::Config.new
8
+ @invalid_filepath = 'files/invalid.file'
9
+ @yaml_filepath = File.join(File.expand_path(File.dirname(__FILE__)), 'files/yaml.yaml')
10
+ end
11
+
12
+ describe '#new' do
13
+ it 'should create instances of Config' do
14
+ expect(@config).to be_an_instance_of Soryo::Config
15
+ end
16
+
17
+ it 'should be a subclass of Hash' do
18
+ expect(@config).to be_a_kind_of Hash
19
+ end
20
+
21
+ it 'should be initialized with default values' do
22
+ expect(@config).to eq(Soryo::DEFAULTS)
23
+ end
24
+ end
25
+
26
+ describe '#merge_with' do
27
+ it "should merge two hashes" do
28
+ hash = Hash["test" => 200, "test_type" => 'test']
29
+ merged_hashes = Soryo::DEFAULTS.merge(hash)
30
+ expect(@config.merge_with(hash)).to eq(merged_hashes)
31
+ end
32
+ end
33
+
34
+ describe '#read_yaml' do
35
+ it "should throw an error if file is not found" do
36
+ expect{@config.read_yaml(@invalid_filepath)}.to raise_error('NoFileFound')
37
+ end
38
+
39
+ it "should merge settings if file is valid" do
40
+ @config.read_yaml(@yaml_filepath)
41
+ yaml_hash = YAML.load(File.open(@yaml_filepath, 'r'))
42
+ merged_hashes = Soryo::DEFAULTS.merge(yaml_hash)
43
+ expect(@config.read_yaml(@yaml_filepath)).to eq(merged_hashes)
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,80 @@
1
+ require_relative '../lib/soryo.rb'
2
+ require 'pathname'
3
+
4
+ describe Soryo::FileInstance do
5
+ before :each do
6
+ @json_filepath = File.join(File.expand_path(File.dirname(__FILE__)), 'files/json.json')
7
+ @yaml_filepath = File.join(File.expand_path(File.dirname(__FILE__)), 'files/yaml.yaml')
8
+ @invalid_filepath = File.join(File.expand_path(File.dirname(__FILE__)), 'files/invalid.bad')
9
+ @nonjson_filepath = File.join(File.expand_path(File.dirname(__FILE__)), 'files/file.file')
10
+
11
+ @json_sample = Soryo::FileInstance.new(@json_filepath)
12
+ @yaml_sample = Soryo::FileInstance.new(@yaml_filepath)
13
+ @invalid_file = Soryo::FileInstance.new(@invalid_filepath)
14
+ @nonjson_file = Soryo::FileInstance.new(@nonjson_filepath)
15
+
16
+ end
17
+
18
+ describe '#new' do
19
+ it "should return a FileInstance object" do
20
+ expect(@json_sample).to be_an_instance_of Soryo::FileInstance
21
+ end
22
+
23
+ it "should have a file_path from initializer" do
24
+ pathname = Pathname.new(@json_filepath)
25
+ expect(@json_sample.file_path).to eq(pathname)
26
+ end
27
+ end
28
+
29
+ describe '#existance?' do
30
+ it "should return true for valid files" do
31
+ expect(@json_sample.existance?).to be true
32
+ end
33
+
34
+ it "should return false for invalid files" do
35
+ expect(@invalid_file.existance?).to be false
36
+ end
37
+ end
38
+
39
+ describe '#shortname' do
40
+ it "should return a filename without its extension" do
41
+ expect(@json_sample.shortname).to eq('json')
42
+ end
43
+ end
44
+
45
+ describe '#to_s' do
46
+ it "should raise error if file not found" do
47
+ expect{@invalid_file.to_s}.to raise_error('NoFileFound')
48
+ end
49
+
50
+ it "should return file contents if file is found" do
51
+ file_contents = File.open(@json_filepath).read
52
+ expect(@json_sample.to_s).to eq(file_contents)
53
+ end
54
+ end
55
+
56
+ describe '#to_hash' do
57
+ it "should raise error if no file found" do
58
+ expect{@invalid_file.to_hash}.to raise_error('NoFileFound')
59
+ end
60
+
61
+ it "should read json if file is json" do
62
+ file_contents = File.open(@json_filepath).read
63
+ json_text = JSON.parse(file_contents)
64
+ expect(@json_sample.to_hash).to eq(json_text)
65
+ expect(@json_sample.to_hash).to be_an_instance_of Hash
66
+ end
67
+
68
+ it "should read yaml if file is yaml" do
69
+ file_contents = File.open(@yaml_filepath).read
70
+ yaml_text = YAML.load(file_contents)
71
+ expect(@yaml_sample.to_hash).to eq(yaml_text)
72
+ expect(@yaml_sample.to_hash).to be_an_instance_of Hash
73
+ end
74
+
75
+ it "should throw error if file is not yaml or JSON" do
76
+ expect{@nonjson_file.to_hash}.to raise_error('Must be a JSON or YAML file')
77
+ end
78
+ end
79
+
80
+ end
File without changes
@@ -0,0 +1,4 @@
1
+ {
2
+ "title" : "Test title",
3
+ "args" : [1,2,3]
4
+ }
@@ -0,0 +1,2 @@
1
+ test: "test"
2
+ test_type: "test_merge"
@@ -0,0 +1,19 @@
1
+ require_relative '../lib/soryo.rb'
2
+
3
+ describe 'Template' do
4
+ before :each do
5
+ @template = Soryo::Template.new('test', 'test2')
6
+ end
7
+
8
+ describe '#new' do
9
+ it "should be of type Template" do
10
+ expect(@template).to be_an_instance_of Soryo::Template
11
+ end
12
+
13
+ it 'should have two strings: template and hash' do
14
+ expect(@template.template).to eq('test')
15
+ expect(@template.hash).to eq('test2')
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,12 @@
1
+ {
2
+ "products": [
3
+ {
4
+ "title": "Test",
5
+ "type": 3
6
+ },
7
+ {
8
+ "title": "Test2",
9
+ "type": 4
10
+ }
11
+ ]
12
+ }
@@ -0,0 +1,4 @@
1
+ {% for product in products %}
2
+ {{product.title}}
3
+ {{product.type}}
4
+ {% endfor %}
@@ -0,0 +1,3 @@
1
+ {
2
+ "title": "Test title - it works!"
3
+ }
@@ -0,0 +1 @@
1
+ Hello, {{title}}
@@ -0,0 +1,963 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5
+ <meta name="viewport" content="width=device-width"/>
6
+ <style>
7
+ /**********************************************
8
+ * Ink v1.0.5 - Copyright 2013 ZURB Inc *
9
+ **********************************************/
10
+
11
+ /* Client-specific Styles & Reset */
12
+
13
+ #outlook a {
14
+ padding:0;
15
+ }
16
+
17
+ body{
18
+ width:100% !important;
19
+ min-width: 100%;
20
+ -webkit-text-size-adjust:100%;
21
+ -ms-text-size-adjust:100%;
22
+ margin:0;
23
+ padding:0;
24
+ }
25
+
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
+ #backgroundTable {
40
+ margin:0;
41
+ padding:0;
42
+ width:100% !important;
43
+ line-height: 100% !important;
44
+ }
45
+
46
+ img {
47
+ outline:none;
48
+ text-decoration:none;
49
+ -ms-interpolation-mode: bicubic;
50
+ width: auto;
51
+ max-width: 100%;
52
+ float: left;
53
+ clear: both;
54
+ display: block;
55
+ }
56
+
57
+ center {
58
+ width: 100%;
59
+ min-width: 580px;
60
+ }
61
+
62
+ a img {
63
+ border: none;
64
+ }
65
+
66
+ p {
67
+ margin: 0 0 0 10px;
68
+ }
69
+
70
+ table {
71
+ border-spacing: 0;
72
+ border-collapse: collapse;
73
+ }
74
+
75
+ td {
76
+ word-break: break-word;
77
+ -webkit-hyphens: auto;
78
+ -moz-hyphens: auto;
79
+ hyphens: auto;
80
+ border-collapse: collapse !important;
81
+ }
82
+
83
+ table, tr, td {
84
+ padding: 0;
85
+ vertical-align: top;
86
+ text-align: left;
87
+ }
88
+
89
+ hr {
90
+ color: #d9d9d9;
91
+ background-color: #d9d9d9;
92
+ height: 1px;
93
+ border: none;
94
+ }
95
+
96
+ /* Responsive Grid */
97
+
98
+ table.body {
99
+ height: 100%;
100
+ width: 100%;
101
+ }
102
+
103
+ table.container {
104
+ width: 580px;
105
+ margin: 0 auto;
106
+ text-align: inherit;
107
+ }
108
+
109
+ table.row {
110
+ padding: 0px;
111
+ width: 100%;
112
+ position: relative;
113
+ }
114
+
115
+ table.container table.row {
116
+ display: block;
117
+ }
118
+
119
+ td.wrapper {
120
+ padding: 10px 20px 0px 0px;
121
+ position: relative;
122
+ }
123
+
124
+ table.columns,
125
+ table.column {
126
+ margin: 0 auto;
127
+ }
128
+
129
+ table.columns td,
130
+ table.column td {
131
+ padding: 0px 0px 10px;
132
+ }
133
+
134
+ table.columns td.sub-columns,
135
+ table.column td.sub-columns,
136
+ table.columns td.sub-column,
137
+ table.column td.sub-column {
138
+ padding-right: 10px;
139
+ }
140
+
141
+ td.sub-column, td.sub-columns {
142
+ min-width: 0px;
143
+ }
144
+
145
+ table.row td.last,
146
+ table.container td.last {
147
+ padding-right: 0px;
148
+ }
149
+
150
+ table.one { width: 30px; }
151
+ table.two { width: 80px; }
152
+ table.three { width: 130px; }
153
+ table.four { width: 180px; }
154
+ table.five { width: 230px; }
155
+ table.six { width: 280px; }
156
+ table.seven { width: 330px; }
157
+ table.eight { width: 380px; }
158
+ table.nine { width: 430px; }
159
+ table.ten { width: 480px; }
160
+ table.eleven { width: 530px; }
161
+ table.twelve { width: 580px; }
162
+
163
+ table.one center { min-width: 30px; }
164
+ table.two center { min-width: 80px; }
165
+ table.three center { min-width: 130px; }
166
+ table.four center { min-width: 180px; }
167
+ table.five center { min-width: 230px; }
168
+ table.six center { min-width: 280px; }
169
+ table.seven center { min-width: 330px; }
170
+ table.eight center { min-width: 380px; }
171
+ table.nine center { min-width: 430px; }
172
+ table.ten center { min-width: 480px; }
173
+ table.eleven center { min-width: 530px; }
174
+ table.twelve center { min-width: 580px; }
175
+
176
+ table.one .panel center { min-width: 10px; }
177
+ table.two .panel center { min-width: 60px; }
178
+ table.three .panel center { min-width: 110px; }
179
+ table.four .panel center { min-width: 160px; }
180
+ table.five .panel center { min-width: 210px; }
181
+ table.six .panel center { min-width: 260px; }
182
+ table.seven .panel center { min-width: 310px; }
183
+ table.eight .panel center { min-width: 360px; }
184
+ table.nine .panel center { min-width: 410px; }
185
+ table.ten .panel center { min-width: 460px; }
186
+ table.eleven .panel center { min-width: 510px; }
187
+ table.twelve .panel center { min-width: 560px; }
188
+
189
+ .body .columns td.one,
190
+ .body .column td.one { width: 8.333333%; }
191
+ .body .columns td.two,
192
+ .body .column td.two { width: 16.666666%; }
193
+ .body .columns td.three,
194
+ .body .column td.three { width: 25%; }
195
+ .body .columns td.four,
196
+ .body .column td.four { width: 33.333333%; }
197
+ .body .columns td.five,
198
+ .body .column td.five { width: 41.666666%; }
199
+ .body .columns td.six,
200
+ .body .column td.six { width: 50%; }
201
+ .body .columns td.seven,
202
+ .body .column td.seven { width: 58.333333%; }
203
+ .body .columns td.eight,
204
+ .body .column td.eight { width: 66.666666%; }
205
+ .body .columns td.nine,
206
+ .body .column td.nine { width: 75%; }
207
+ .body .columns td.ten,
208
+ .body .column td.ten { width: 83.333333%; }
209
+ .body .columns td.eleven,
210
+ .body .column td.eleven { width: 91.666666%; }
211
+ .body .columns td.twelve,
212
+ .body .column td.twelve { width: 100%; }
213
+
214
+ td.offset-by-one { padding-left: 50px; }
215
+ td.offset-by-two { padding-left: 100px; }
216
+ td.offset-by-three { padding-left: 150px; }
217
+ td.offset-by-four { padding-left: 200px; }
218
+ td.offset-by-five { padding-left: 250px; }
219
+ td.offset-by-six { padding-left: 300px; }
220
+ td.offset-by-seven { padding-left: 350px; }
221
+ td.offset-by-eight { padding-left: 400px; }
222
+ td.offset-by-nine { padding-left: 450px; }
223
+ td.offset-by-ten { padding-left: 500px; }
224
+ td.offset-by-eleven { padding-left: 550px; }
225
+
226
+ td.expander {
227
+ visibility: hidden;
228
+ width: 0px;
229
+ padding: 0 !important;
230
+ }
231
+
232
+ table.columns .text-pad,
233
+ table.column .text-pad {
234
+ padding-left: 10px;
235
+ padding-right: 10px;
236
+ }
237
+
238
+ table.columns .left-text-pad,
239
+ table.columns .text-pad-left,
240
+ table.column .left-text-pad,
241
+ table.column .text-pad-left {
242
+ padding-left: 10px;
243
+ }
244
+
245
+ table.columns .right-text-pad,
246
+ table.columns .text-pad-right,
247
+ table.column .right-text-pad,
248
+ table.column .text-pad-right {
249
+ padding-right: 10px;
250
+ }
251
+
252
+ /* Block Grid */
253
+
254
+ .block-grid {
255
+ width: 100%;
256
+ max-width: 580px;
257
+ }
258
+
259
+ .block-grid td {
260
+ display: inline-block;
261
+ padding:10px;
262
+ }
263
+
264
+ .two-up td {
265
+ width:270px;
266
+ }
267
+
268
+ .three-up td {
269
+ width:173px;
270
+ }
271
+
272
+ .four-up td {
273
+ width:125px;
274
+ }
275
+
276
+ .five-up td {
277
+ width:96px;
278
+ }
279
+
280
+ .six-up td {
281
+ width:76px;
282
+ }
283
+
284
+ .seven-up td {
285
+ width:62px;
286
+ }
287
+
288
+ .eight-up td {
289
+ width:52px;
290
+ }
291
+
292
+ /* Alignment & Visibility Classes */
293
+
294
+ table.center, td.center {
295
+ text-align: center;
296
+ }
297
+
298
+ h1.center,
299
+ h2.center,
300
+ h3.center,
301
+ h4.center,
302
+ h5.center,
303
+ h6.center {
304
+ text-align: center;
305
+ }
306
+
307
+ span.center {
308
+ display: block;
309
+ width: 100%;
310
+ text-align: center;
311
+ }
312
+
313
+ img.center {
314
+ margin: 0 auto;
315
+ float: none;
316
+ }
317
+
318
+ .show-for-small,
319
+ .hide-for-desktop {
320
+ display: none;
321
+ }
322
+
323
+ /* Typography */
324
+
325
+ body, table.body, h1, h2, h3, h4, h5, h6, p, td {
326
+ color: #222222;
327
+ font-family: "Helvetica", "Arial", sans-serif;
328
+ font-weight: normal;
329
+ padding:0;
330
+ margin: 0;
331
+ text-align: left;
332
+ line-height: 1.3;
333
+ }
334
+
335
+ h1, h2, h3, h4, h5, h6 {
336
+ word-break: normal;
337
+ }
338
+
339
+ h1 {font-size: 40px;}
340
+ h2 {font-size: 36px;}
341
+ h3 {font-size: 32px;}
342
+ h4 {font-size: 28px;}
343
+ h5 {font-size: 24px;}
344
+ h6 {font-size: 20px;}
345
+ body, table.body, p, td {font-size: 14px;line-height:19px;}
346
+
347
+ p.lead, p.lede, p.leed {
348
+ font-size: 18px;
349
+ line-height:21px;
350
+ }
351
+
352
+ p {
353
+ margin-bottom: 10px;
354
+ }
355
+
356
+ small {
357
+ font-size: 10px;
358
+ }
359
+
360
+ a {
361
+ color: #2ba6cb;
362
+ text-decoration: none;
363
+ }
364
+
365
+ a:hover {
366
+ color: #2795b6 !important;
367
+ }
368
+
369
+ a:active {
370
+ color: #2795b6 !important;
371
+ }
372
+
373
+ a:visited {
374
+ color: #2ba6cb !important;
375
+ }
376
+
377
+ h1 a,
378
+ h2 a,
379
+ h3 a,
380
+ h4 a,
381
+ h5 a,
382
+ h6 a {
383
+ color: #2ba6cb;
384
+ }
385
+
386
+ h1 a:active,
387
+ h2 a:active,
388
+ h3 a:active,
389
+ h4 a:active,
390
+ h5 a:active,
391
+ h6 a:active {
392
+ color: #2ba6cb !important;
393
+ }
394
+
395
+ h1 a:visited,
396
+ h2 a:visited,
397
+ h3 a:visited,
398
+ h4 a:visited,
399
+ h5 a:visited,
400
+ h6 a:visited {
401
+ color: #2ba6cb !important;
402
+ }
403
+
404
+ /* Panels */
405
+
406
+ .panel {
407
+ background: #f2f2f2;
408
+ border: 1px solid #d9d9d9;
409
+ padding: 10px !important;
410
+ }
411
+
412
+ .sub-grid table {
413
+ width: 100%;
414
+ }
415
+
416
+ .sub-grid td.sub-columns {
417
+ padding-bottom: 0;
418
+ }
419
+
420
+ /* Buttons */
421
+
422
+ table.button,
423
+ table.tiny-button,
424
+ table.small-button,
425
+ table.medium-button,
426
+ table.large-button {
427
+ width: 100%;
428
+ overflow: hidden;
429
+ }
430
+
431
+ table.button td,
432
+ table.tiny-button td,
433
+ table.small-button td,
434
+ table.medium-button td,
435
+ table.large-button td {
436
+ display: block;
437
+ width: auto !important;
438
+ text-align: center;
439
+ background: #2ba6cb;
440
+ border: 1px solid #2284a1;
441
+ color: #ffffff;
442
+ padding: 8px 0;
443
+ }
444
+
445
+ table.tiny-button td {
446
+ padding: 5px 0 4px;
447
+ }
448
+
449
+ table.small-button td {
450
+ padding: 8px 0 7px;
451
+ }
452
+
453
+ table.medium-button td {
454
+ padding: 12px 0 10px;
455
+ }
456
+
457
+ table.large-button td {
458
+ padding: 21px 0 18px;
459
+ }
460
+
461
+ table.button td a,
462
+ table.tiny-button td a,
463
+ table.small-button td a,
464
+ table.medium-button td a,
465
+ table.large-button td a {
466
+ font-weight: bold;
467
+ text-decoration: none;
468
+ font-family: Helvetica, Arial, sans-serif;
469
+ color: #ffffff;
470
+ font-size: 16px;
471
+ }
472
+
473
+ table.tiny-button td a {
474
+ font-size: 12px;
475
+ font-weight: normal;
476
+ }
477
+
478
+ table.small-button td a {
479
+ font-size: 16px;
480
+ }
481
+
482
+ table.medium-button td a {
483
+ font-size: 20px;
484
+ }
485
+
486
+ table.large-button td a {
487
+ font-size: 24px;
488
+ }
489
+
490
+ table.button:hover td,
491
+ table.button:visited td,
492
+ table.button:active td {
493
+ background: #2795b6 !important;
494
+ }
495
+
496
+ table.button:hover td a,
497
+ table.button:visited td a,
498
+ table.button:active td a {
499
+ color: #fff !important;
500
+ }
501
+
502
+ table.button:hover td,
503
+ table.tiny-button:hover td,
504
+ table.small-button:hover td,
505
+ table.medium-button:hover td,
506
+ table.large-button:hover td {
507
+ background: #2795b6 !important;
508
+ }
509
+
510
+ table.button:hover td a,
511
+ table.button:active td a,
512
+ table.button td a:visited,
513
+ table.tiny-button:hover td a,
514
+ table.tiny-button:active td a,
515
+ table.tiny-button td a:visited,
516
+ table.small-button:hover td a,
517
+ table.small-button:active td a,
518
+ table.small-button td a:visited,
519
+ table.medium-button:hover td a,
520
+ table.medium-button:active td a,
521
+ table.medium-button td a:visited,
522
+ table.large-button:hover td a,
523
+ table.large-button:active td a,
524
+ table.large-button td a:visited {
525
+ color: #ffffff !important;
526
+ }
527
+
528
+ table.secondary td {
529
+ background: #e9e9e9;
530
+ border-color: #d0d0d0;
531
+ color: #555;
532
+ }
533
+
534
+ table.secondary td a {
535
+ color: #555;
536
+ }
537
+
538
+ table.secondary:hover td {
539
+ background: #d0d0d0 !important;
540
+ color: #555;
541
+ }
542
+
543
+ table.secondary:hover td a,
544
+ table.secondary td a:visited,
545
+ table.secondary:active td a {
546
+ color: #555 !important;
547
+ }
548
+
549
+ table.success td {
550
+ background: #5da423;
551
+ border-color: #457a1a;
552
+ }
553
+
554
+ table.success:hover td {
555
+ background: #457a1a !important;
556
+ }
557
+
558
+ table.alert td {
559
+ background: #c60f13;
560
+ border-color: #970b0e;
561
+ }
562
+
563
+ table.alert:hover td {
564
+ background: #970b0e !important;
565
+ }
566
+
567
+ table.radius td {
568
+ -webkit-border-radius: 3px;
569
+ -moz-border-radius: 3px;
570
+ border-radius: 3px;
571
+ }
572
+
573
+ table.round td {
574
+ -webkit-border-radius: 500px;
575
+ -moz-border-radius: 500px;
576
+ border-radius: 500px;
577
+ }
578
+
579
+ /* Outlook First */
580
+
581
+ body.outlook p {
582
+ display: inline !important;
583
+ }
584
+
585
+ /* Media Queries */
586
+
587
+ @media only screen and (max-width: 600px) {
588
+
589
+ table[class="body"] img {
590
+ width: auto !important;
591
+ height: auto !important;
592
+ }
593
+
594
+ table[class="body"] center {
595
+ min-width: 0 !important;
596
+ }
597
+
598
+ table[class="body"] .container {
599
+ width: 95% !important;
600
+ }
601
+
602
+ table[class="body"] .row {
603
+ width: 100% !important;
604
+ display: block !important;
605
+ }
606
+
607
+ table[class="body"] .wrapper {
608
+ display: block !important;
609
+ padding-right: 0 !important;
610
+ }
611
+
612
+ table[class="body"] .columns,
613
+ table[class="body"] .column {
614
+ table-layout: fixed !important;
615
+ float: none !important;
616
+ width: 100% !important;
617
+ padding-right: 0px !important;
618
+ padding-left: 0px !important;
619
+ display: block !important;
620
+ }
621
+
622
+ table[class="body"] .wrapper.first .columns,
623
+ table[class="body"] .wrapper.first .column {
624
+ display: table !important;
625
+ }
626
+
627
+ table[class="body"] table.columns td,
628
+ table[class="body"] table.column td {
629
+ width: 100% !important;
630
+ }
631
+
632
+ table[class="body"] .columns td.one,
633
+ table[class="body"] .column td.one { width: 8.333333% !important; }
634
+ table[class="body"] .columns td.two,
635
+ table[class="body"] .column td.two { width: 16.666666% !important; }
636
+ table[class="body"] .columns td.three,
637
+ table[class="body"] .column td.three { width: 25% !important; }
638
+ table[class="body"] .columns td.four,
639
+ table[class="body"] .column td.four { width: 33.333333% !important; }
640
+ table[class="body"] .columns td.five,
641
+ table[class="body"] .column td.five { width: 41.666666% !important; }
642
+ table[class="body"] .columns td.six,
643
+ table[class="body"] .column td.six { width: 50% !important; }
644
+ table[class="body"] .columns td.seven,
645
+ table[class="body"] .column td.seven { width: 58.333333% !important; }
646
+ table[class="body"] .columns td.eight,
647
+ table[class="body"] .column td.eight { width: 66.666666% !important; }
648
+ table[class="body"] .columns td.nine,
649
+ table[class="body"] .column td.nine { width: 75% !important; }
650
+ table[class="body"] .columns td.ten,
651
+ table[class="body"] .column td.ten { width: 83.333333% !important; }
652
+ table[class="body"] .columns td.eleven,
653
+ table[class="body"] .column td.eleven { width: 91.666666% !important; }
654
+ table[class="body"] .columns td.twelve,
655
+ table[class="body"] .column td.twelve { width: 100% !important; }
656
+
657
+ table[class="body"] td.offset-by-one,
658
+ table[class="body"] td.offset-by-two,
659
+ table[class="body"] td.offset-by-three,
660
+ table[class="body"] td.offset-by-four,
661
+ table[class="body"] td.offset-by-five,
662
+ table[class="body"] td.offset-by-six,
663
+ table[class="body"] td.offset-by-seven,
664
+ table[class="body"] td.offset-by-eight,
665
+ table[class="body"] td.offset-by-nine,
666
+ table[class="body"] td.offset-by-ten,
667
+ table[class="body"] td.offset-by-eleven {
668
+ padding-left: 0 !important;
669
+ }
670
+
671
+ table[class="body"] table.columns td.expander {
672
+ width: 1px !important;
673
+ }
674
+
675
+ table[class="body"] .right-text-pad,
676
+ table[class="body"] .text-pad-right {
677
+ padding-left: 10px !important;
678
+ }
679
+
680
+ table[class="body"] .left-text-pad,
681
+ table[class="body"] .text-pad-left {
682
+ padding-right: 10px !important;
683
+ }
684
+
685
+ table[class="body"] .hide-for-small,
686
+ table[class="body"] .show-for-desktop {
687
+ display: none !important;
688
+ }
689
+
690
+ table[class="body"] .show-for-small,
691
+ table[class="body"] .hide-for-desktop {
692
+ display: inherit !important;
693
+ }
694
+ }
695
+
696
+ </style>
697
+ <style>
698
+
699
+ table.facebook td {
700
+ background: #3b5998;
701
+ border-color: #2d4473;
702
+ }
703
+
704
+ table.facebook:hover td {
705
+ background: #2d4473 !important;
706
+ }
707
+
708
+ table.twitter td {
709
+ background: #00acee;
710
+ border-color: #0087bb;
711
+ }
712
+
713
+ table.twitter:hover td {
714
+ background: #0087bb !important;
715
+ }
716
+
717
+ table.google-plus td {
718
+ background-color: #DB4A39;
719
+ border-color: #CC0000;
720
+ }
721
+
722
+ table.google-plus:hover td {
723
+ background: #CC0000 !important;
724
+ }
725
+
726
+ .template-label {
727
+ color: #ffffff;
728
+ font-weight: bold;
729
+ font-size: 11px;
730
+ }
731
+
732
+ .callout .panel {
733
+ background: #ECF8FF;
734
+ border-color: #b9e5ff;
735
+ }
736
+
737
+ .header {
738
+ background: #999999;
739
+ }
740
+
741
+ .footer .wrapper {
742
+ background: #ebebeb;
743
+ }
744
+
745
+ .footer h5 {
746
+ padding-bottom: 10px;
747
+ }
748
+
749
+ table.columns .text-pad {
750
+ padding-left: 10px;
751
+ padding-right: 10px;
752
+ }
753
+
754
+ table.columns .left-text-pad {
755
+ padding-left: 10px;
756
+ }
757
+
758
+ table.columns .right-text-pad {
759
+ padding-right: 10px;
760
+ }
761
+
762
+ @media only screen and (max-width: 600px) {
763
+
764
+ table[class="body"] .right-text-pad {
765
+ padding-left: 10px !important;
766
+ }
767
+
768
+ table[class="body"] .left-text-pad {
769
+ padding-right: 10px !important;
770
+ }
771
+ }
772
+
773
+ </style>
774
+ </head>
775
+ <body>
776
+ <table class="body">
777
+ <tr>
778
+ <td class="center" align="center" valign="top">
779
+ <center>
780
+
781
+ <table class="container">
782
+ <tr>
783
+ <td>
784
+
785
+ <!-- content start -->
786
+ <!-- logo image -->
787
+ <table class="row">
788
+ <tr>
789
+ <td class="wrapper last">
790
+
791
+ <table class="twelve columns">
792
+ <tr>
793
+ <td>
794
+
795
+ <img width="580" height="300" src="logo.png">
796
+
797
+ </td>
798
+ <td class="expander"></td>
799
+ </tr>
800
+ </table>
801
+
802
+ </td>
803
+ </tr>
804
+ </table>
805
+ <!-- logo image ends -->
806
+
807
+ <!-- important announcment, if needed -->
808
+ {% if announcement_text %}
809
+ <table class="row callout">
810
+ <tr>
811
+ <td class="wrapper last">
812
+
813
+ <table class="twelve columns">
814
+ <tr>
815
+ <td class="panel">
816
+
817
+ <p>{{ announcement_text }}</p>
818
+
819
+ </td>
820
+ <td class="expander"></td>
821
+ </tr>
822
+ </table>
823
+
824
+ </td>
825
+ </tr>
826
+ </table>
827
+ {% endif %}
828
+ <!-- Announcment text ends -->
829
+
830
+ <!-- General text -->
831
+ <table class="row">
832
+ <tr>
833
+ <td class="wrapper last">
834
+
835
+ <table class="twelve columns">
836
+ <tr>
837
+ <td>
838
+ <br />
839
+ <p>{{ general_text }}</p>
840
+
841
+ </td>
842
+ <td class="expander"></td>
843
+ </tr>
844
+ </table>
845
+
846
+ </td>
847
+ </tr>
848
+ </table>
849
+ <!-- General text ends -->
850
+
851
+
852
+ <!-- Looped through announcement row -->
853
+ {% for event in events %}
854
+ <table class="row">
855
+ <tr>
856
+ <td class="wrapper">
857
+
858
+ <table class="three columns">
859
+ <tr>
860
+ <td>
861
+
862
+ <img height="130" width="130" src="{{ event.img }}">
863
+
864
+ </td>
865
+ <td class="expander"></td>
866
+ </tr>
867
+ </table>
868
+
869
+ </td>
870
+
871
+ <td class="wrapper last offset-by-four">
872
+ <table class="five columns">
873
+ <tr>
874
+ <td>
875
+ <h1> {{event.name}} </h1>
876
+ <p> {{event.desc}} </p>
877
+ </td>
878
+ <td class="expander"></td>
879
+ </tr>
880
+ </table>
881
+ </td>
882
+ </tr>
883
+ </table>
884
+ <!-- Announcement row ends -->
885
+ {% endfor %}
886
+
887
+
888
+ <table class="row">
889
+ <tr>
890
+
891
+ <td class="wrapper">
892
+
893
+ <table class="four columns">
894
+ <tr>
895
+ <img height="60" width="60" src="http://placehold.it/60x60A>"
896
+ </tr>
897
+ <td class="expander"></td>
898
+ </tr>
899
+ </table>
900
+
901
+ </td>
902
+ <td class="wrapper">
903
+
904
+ <table class="four columns">
905
+ <tr>
906
+ <td class="center"
907
+ <center>
908
+ <img height="60" width="60" src="http://placehold.it/60x60A>"
909
+ </center>
910
+ </td>
911
+ </tr>
912
+ <td class="expander"></td>
913
+ </tr>
914
+ </table>
915
+
916
+ </td>
917
+ <td class="wrapper last">
918
+
919
+ <table class="four columns">
920
+ <tr>
921
+
922
+ <img height="60" width="60" src="http://placehold.it/60x60A>"
923
+ </tr>
924
+ <td class="expander"></td>
925
+ </tr>
926
+ </table>
927
+
928
+ </td>
929
+
930
+ </tr>
931
+ </table>
932
+
933
+
934
+ <table class="row">
935
+ <tr>
936
+ <td class="wrapper last">
937
+
938
+ <table class="twelve columns">
939
+ <tr>
940
+ <td align="center">
941
+ <center>
942
+ <p style="text-align:center;"><a href="#">Unsubscribe</a></p>
943
+ </center>
944
+ </td>
945
+ <td class="expander"></td>
946
+ </tr>
947
+ </table>
948
+
949
+ </td>
950
+ </tr>
951
+ </table>
952
+
953
+ <!-- container end below -->
954
+ </td>
955
+ </tr>
956
+ </table>
957
+
958
+ </center>
959
+ </td>
960
+ </tr>
961
+ </table>
962
+ </body>
963
+ </html>