html_email_creator 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile.lock +49 -0
  4. data/README.markdown +5 -0
  5. data/Rakefile +7 -0
  6. data/bin/html_email_creator +35 -0
  7. data/html_email_creator.gemspec +41 -0
  8. data/lib/html_email_creator/email.rb +93 -0
  9. data/lib/html_email_creator/email_creator.rb +45 -0
  10. data/lib/html_email_creator/email_version.rb +26 -0
  11. data/lib/html_email_creator/extensions.rb +46 -0
  12. data/lib/html_email_creator/filters.rb +9 -0
  13. data/lib/html_email_creator/formatter.rb +30 -0
  14. data/lib/html_email_creator/formatters/formatter.rb +31 -0
  15. data/lib/html_email_creator/formatters/html_email.rb +24 -0
  16. data/lib/html_email_creator/formatters/markdown.rb +24 -0
  17. data/lib/html_email_creator/formatters/plain_text_email.rb +22 -0
  18. data/lib/html_email_creator/formatters/unknown_formatter.rb +17 -0
  19. data/lib/html_email_creator/helper.rb +25 -0
  20. data/lib/html_email_creator/information.rb +4 -0
  21. data/lib/html_email_creator/layout.rb +15 -0
  22. data/lib/html_email_creator/processor.rb +125 -0
  23. data/lib/html_email_creator/settings.rb +95 -0
  24. data/lib/html_email_creator/tags/include_tag.rb +71 -0
  25. data/lib/html_email_creator/version.rb +3 -0
  26. data/lib/html_email_creator.rb +46 -0
  27. data/spec/fixtures/complex_with_config/.html_config.yaml +11 -0
  28. data/spec/fixtures/complex_with_config/Emails/polite_email.yaml +7 -0
  29. data/spec/fixtures/complex_with_config/Includes/Emails/love.md +1 -0
  30. data/spec/fixtures/complex_with_config/Includes/Footers/polite.md +3 -0
  31. data/spec/fixtures/complex_with_config/Layouts/.keep +0 -0
  32. data/spec/fixtures/complex_with_config/Layouts/basic.liquid +25 -0
  33. data/spec/fixtures/complex_with_config/Output/.keep +0 -0
  34. data/spec/fixtures/default_config/Emails/Newsletter/.keep +0 -0
  35. data/spec/fixtures/default_config/Layouts/.keep +0 -0
  36. data/spec/fixtures/default_config/Output/.keep +0 -0
  37. data/spec/fixtures/with_config/.html_config.yaml +11 -0
  38. data/spec/fixtures/with_config/Emails/first_email.yaml +7 -0
  39. data/spec/fixtures/with_config/Includes/Emails/barfoo.md +1 -0
  40. data/spec/fixtures/with_config/Includes/Emails/foobar.md +1 -0
  41. data/spec/fixtures/with_config/Includes/Quotes/henry_ford.txt +1 -0
  42. data/spec/fixtures/with_config/Layouts/.keep +0 -0
  43. data/spec/fixtures/with_config/Layouts/simple.liquid +7 -0
  44. data/spec/fixtures/with_config/Output/.keep +0 -0
  45. data/spec/html_email_creator/email_creator_spec.rb +119 -0
  46. data/spec/html_email_creator/email_spec.rb +29 -0
  47. data/spec/html_email_creator/formatter_spec.rb +40 -0
  48. data/spec/html_email_creator/layout_spec.rb +55 -0
  49. data/spec/html_email_creator/processor_spec.rb +111 -0
  50. data/spec/html_email_creator/settings_spec.rb +70 -0
  51. data/spec/html_email_creator/tags/include_tag_spec.rb +11 -0
  52. data/spec/spec_helper.rb +32 -0
  53. metadata +244 -0
@@ -0,0 +1,11 @@
1
+ layouts_path: "Layouts"
2
+ output_path: "Output"
3
+ emails_path: "Emails"
4
+ includes_path: "Includes"
5
+ cdn_url: "http://cdn.example.com"
6
+ extensions:
7
+ built_in:
8
+ - "aweber"
9
+ custom:
10
+ logo: "**Logo**: WOHOO."
11
+ great: "GREAT!"
@@ -0,0 +1,7 @@
1
+ config:
2
+ output: "basic_text"
3
+ layout: "basic.liquid"
4
+ data:
5
+ title_content: "A variant"
6
+ header_1_content: "{{ logo }}"
7
+ header_2_content: "{% include 'Emails/love.md' what: 'iPhone' %}"
@@ -0,0 +1 @@
1
+ I really love {{ what }}. {{ great }}
@@ -0,0 +1,3 @@
1
+ Kind Regards,
2
+
3
+ {{ name }}
File without changes
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
5
+ <title>{{ title_content }}</title>
6
+ </head>
7
+ <body>
8
+
9
+ <style type="text/css">
10
+ .h1 div{font-family:Helvetica}
11
+ ul{margin: 5px 5px 5px 5px}
12
+ </style>
13
+
14
+ <h1>Header 1 starts</h1>
15
+
16
+ Hi {{ full_name }},
17
+
18
+ {{ header_1_content }}
19
+
20
+ <h2>Header 2 starts</h2>
21
+
22
+ {{ header_2_content }}
23
+
24
+ </body>
25
+ </html>
File without changes
File without changes
File without changes
@@ -0,0 +1,11 @@
1
+ layouts_path: "Layouts"
2
+ output_path: "Output"
3
+ emails_path: "Emails"
4
+ includes_path: "Includes"
5
+ cdn_url: "http://cdn.example.com"
6
+ extensions:
7
+ built_in:
8
+ - "aweber"
9
+ custom:
10
+ foobar: "Hi, this is foobar."
11
+ great: "Hi, this is **great**"
@@ -0,0 +1,7 @@
1
+ config:
2
+ output: "first"
3
+ layout: "simple.liquid"
4
+ data:
5
+ first_content: "{% include 'Emails/foobar.md' %}"
6
+ second_content: "{% include 'Emails/barfoo.md' %}"
7
+ third_content: "{{ 'foo/bar' | photo: 'alt text' }}"
@@ -0,0 +1 @@
1
+ A bore is a person who opens his {{ what }} and puts his feats in it.
File without changes
@@ -0,0 +1,7 @@
1
+ This is simple template.
2
+
3
+ {{ first_content }}
4
+
5
+ {{ second_content }}
6
+
7
+ {{ third_content }}
File without changes
@@ -0,0 +1,119 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe HtmlEmailCreator::EmailCreator do
4
+ let(:creator) { HtmlEmailCreator::EmailCreator.new }
5
+ let(:email) { fixture_dir("complex_with_config", "Emails", "polite_email.yaml") }
6
+ let(:expected_basic_text_html) {
7
+ html = <<eos
8
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
9
+ <html>
10
+ <head>
11
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
12
+ <title>A variant</title>
13
+ </head>
14
+ <body>
15
+
16
+ <div class="h1"><div style="font-family: Helvetica;">Header 1 starts</div></div>
17
+
18
+ Hi {!name_fix},
19
+
20
+ **Logo**: WOHOO.
21
+
22
+ <div class="h2"><div>Header 2 starts</div></div>
23
+
24
+ <p>I really love iPhone. GREAT!</p>
25
+
26
+ </body>
27
+ </html>
28
+ eos
29
+ }
30
+
31
+ let(:expected_basic_text_txt) {
32
+ text = <<eos
33
+ =============================================================================
34
+ Header 1 starts
35
+
36
+ Hi {!name_fix},
37
+
38
+ **Logo**: WOHOO.
39
+
40
+ -----------------------------------------------------------------------------
41
+ Header 2 starts
42
+
43
+ I really love iPhone. GREAT!
44
+ eos
45
+ text.strip
46
+ }
47
+
48
+ let(:expected_first_html) {
49
+ html = <<eos
50
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
51
+ <html><body>
52
+ <p>This is simple template.
53
+
54
+ </p>
55
+ <p>foo bar</p>
56
+
57
+ <p>bar foo</p>
58
+
59
+ <img src="http://cdn.example.com/foo/bar" alt="alt text" border="0">
60
+ </body></html>
61
+ eos
62
+ }
63
+
64
+ let(:expected_first_txt) {
65
+ text = <<eos
66
+ This is simple template.
67
+
68
+ foo bar
69
+
70
+ bar foo
71
+
72
+ alt text (http://cdn.example.com/foo/bar)
73
+ eos
74
+ text.strip
75
+ }
76
+
77
+ describe "HTML mail" do
78
+ it "should create well formed and expected HTML mail" do
79
+ creator.create_html_email(email).get.should == expected_basic_text_html
80
+ creator.create_email(email, HtmlEmailCreator::Formatters::HtmlEmail.id).get.should == expected_basic_text_html
81
+ end
82
+ end
83
+
84
+ describe "Plain text mail" do
85
+ it "should create well formed and expected plain text email" do
86
+ creator.create_plain_text_email(email).get.should == expected_basic_text_txt
87
+ end
88
+ end
89
+
90
+ describe "Saving email to a filesystem" do
91
+ after(:each) { clean_fixture_output }
92
+
93
+ it "should be possible to store emails recursively" do
94
+ creator.save_emails(".").should be_empty
95
+ creator.save_emails(".", true).should_not be_empty
96
+ end
97
+
98
+ it "should store all correct versions of emails recursively" do
99
+ emails = creator.save_emails(".", true)
100
+
101
+ read_fixture("complex_with_config", "Output", "basic_text.html").should == expected_basic_text_html
102
+ read_fixture("complex_with_config", "Output", "basic_text.txt").should == expected_basic_text_txt
103
+ read_fixture("with_config", "Output", "first.html").should == expected_first_html
104
+ read_fixture("with_config", "Output", "first.txt").should == expected_first_txt
105
+ end
106
+
107
+ it "should store only one file if needed using absolute paths" do
108
+ IO.read(creator.create_html_email(fixture_dir("complex_with_config", "Emails", "polite_email.yaml")).save).should == expected_basic_text_html
109
+ end
110
+
111
+ it "should store only one file if needed using relative paths" do
112
+ run_in_fixture_dir("complex_with_config") do
113
+ email_creator = HtmlEmailCreator::EmailCreator.new
114
+ IO.read(email_creator.create_html_email(File.join("Emails", "polite_email.yaml")).save).should == expected_basic_text_html
115
+ end
116
+ end
117
+ end
118
+ end
119
+
@@ -0,0 +1,29 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe HtmlEmailCreator::Email do
4
+ let(:email) {
5
+ HtmlEmailCreator::Email.new(fixture_dir("with_config", "Emails", "first_email.yaml")).render_only(:html_email)
6
+ }
7
+
8
+ let(:expected_html) {
9
+ html = <<eos
10
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
11
+ <html><body>
12
+ <p>This is simple template.
13
+
14
+ </p>
15
+ <p>foo bar</p>
16
+
17
+ <p>bar foo</p>
18
+
19
+ <img src="http://cdn.example.com/foo/bar" alt="alt text" border="0">
20
+ </body></html>
21
+ eos
22
+ }
23
+
24
+ it "should render markdown and liquid templates using settings and email configuration" do
25
+ run_in_fixture_dir("with_config") do
26
+ email.get.should eql(expected_html)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,40 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe HtmlEmailCreator::Formatter do
4
+ describe "Markdown" do
5
+ let(:md) { HtmlEmailCreator::Formatters::Markdown.id }
6
+
7
+ it "should convert correctly" do
8
+ HtmlEmailCreator::Formatter.new("**I am strong**").find(md).format.should eql("<p><strong>I am strong</strong></p>")
9
+ end
10
+
11
+ it "should support table extension" do
12
+ markdown = <<-eos
13
+ | First | Second | Third |
14
+ |:------|:-------|:------|
15
+ | 1 | 2 | 3 |
16
+ eos
17
+
18
+ html = <<eos
19
+ <table>
20
+ <thead>
21
+ <tr>
22
+ <th style="text-align: left">First</th>
23
+ <th style="text-align: left">Second</th>
24
+ <th style="text-align: left">Third</th>
25
+ </tr>
26
+ </thead>
27
+ <tbody>
28
+ <tr>
29
+ <td style="text-align: left">1</td>
30
+ <td style="text-align: left">2</td>
31
+ <td style="text-align: left">3</td>
32
+ </tr>
33
+ </tbody>
34
+ </table>
35
+ eos
36
+
37
+ HtmlEmailCreator::Formatter.new(markdown).find(md).format.should eql(html.strip)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,55 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe HtmlEmailCreator::Layout do
4
+
5
+ describe "with custom variables" do
6
+ it "should replace variables" do
7
+ HtmlEmailCreator::Layout.new("foo {{ bar }}").to_html("bar" => "great bar").should eql("foo great bar")
8
+ end
9
+
10
+ it "should just ignore the variable if the variable was not found" do
11
+ HtmlEmailCreator::Layout.new("foo {{ bar }}").to_html.should eql("foo ")
12
+ end
13
+ end
14
+
15
+ describe "with built-in extensions" do
16
+
17
+ describe "aweber" do
18
+ let(:aweber) { HtmlEmailCreator::Extensions.new.built_in("aweber") }
19
+ let(:none) { {} }
20
+
21
+ it "should replace Aweber extension keys correctly if aweber extension is being used" do
22
+ HtmlEmailCreator::Layout.new("{{ after_7_days }}", aweber).to_html.should eql('{!date dayname+7}')
23
+ HtmlEmailCreator::Layout.new("{{ after_7_days }}", none).to_html.should eql('')
24
+ end
25
+
26
+ it "should replace Aweber extension keys correctly if aweber extension is being used in settings" do
27
+ run_in_fixture_dir("with_config") do
28
+ HtmlEmailCreator::Layout.new("{{ after_7_days }}").to_html.should eql('{!date dayname+7}')
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ describe "with custom extensions" do
35
+
36
+ it "should replace custom extension keys correctly use custom extensions from configuration to render the layout" do
37
+ run_in_fixture_dir("with_config") do
38
+ HtmlEmailCreator::Layout.new("{{ foobar }}").to_html.should eql('Hi, this is foobar.')
39
+ HtmlEmailCreator::Layout.new("{{ great }}").to_html.should eql('Hi, this is **great**')
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ describe "with built-in filters" do
46
+
47
+ it "should generate photo url correctly" do
48
+ run_in_fixture_dir("with_config") do
49
+ markdown = '{{ "hello/world.jpg" | photo: "Custom alt text" }}'
50
+ output = '<img src="http://cdn.example.com/hello/world.jpg" alt="Custom alt text" border="0" />'
51
+ HtmlEmailCreator::Layout.new(markdown).to_html.should eql(output)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,111 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
+
3
+ describe HtmlEmailCreator::Processor do
4
+
5
+ let(:processor) {
6
+ html = <<-eos
7
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
8
+ <html>
9
+ <head>
10
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
11
+ <title>Title</title>
12
+ </head>
13
+ <body>
14
+
15
+ <style type="text/css">
16
+ .h1 div{font-family:Helvetica}
17
+ ul{margin: 5px 5px 5px 5px}
18
+ </style>
19
+
20
+ <h1>Header 1</h1>
21
+
22
+ <table class="inline">
23
+ <tr><td>col1</td><td>col2</td>
24
+ <tr><td>row 1 col 1</td><td>row 1 col 2</td>
25
+ <tr><td>row 2 col 1</td><td>row 2 col 2</td>
26
+ </table>
27
+
28
+ This is simple email with <a href="http://link1.com">link</a>
29
+
30
+ <p><img src="http://cdn.example.com/foo/bar" alt="Great image" border="0" /></p>
31
+
32
+ <p><a href="http://signup"><img src="http://cdn.example.com/foo/bar" alt="Signup" border="0" /></a></p>
33
+
34
+ <h2>Header 2</h2>
35
+
36
+ <ul>
37
+ <li>list 1</li>
38
+ <li>list 2</li>
39
+ </ul>
40
+ </body>
41
+ </html>
42
+ eos
43
+
44
+ HtmlEmailCreator::Processor.new(html)
45
+ }
46
+
47
+ describe "#to_html" do
48
+ let(:html) { processor.to_html }
49
+
50
+ it "should wrap headers with divs" do
51
+ html.should include('<div class="h1"><div style="font-family: Helvetica;">Header 1</div></div>')
52
+ end
53
+
54
+ it "should inline styles" do
55
+ html.should include('<ul style="margin: 5px 5px 5px 5px;">')
56
+ end
57
+
58
+ end
59
+
60
+ describe "#to_plain_text" do
61
+ let(:text) { processor.to_plain_text }
62
+
63
+ it "format plain text message in a nice way" do
64
+ expected_output = <<-eos
65
+ =============================================================================
66
+ Header 1
67
+
68
+ col1
69
+ * row 1 col 1
70
+ * row 2 col 1
71
+
72
+ col2
73
+ * row 1 col 2
74
+ * row 2 col 2
75
+
76
+ This is simple email with link (http://link1.com)
77
+
78
+ Great image (http://cdn.example.com/foo/bar)
79
+
80
+ Signup (http://signup)
81
+
82
+ -----------------------------------------------------------------------------
83
+ Header 2
84
+
85
+ - list 1
86
+ - list 2
87
+ eos
88
+
89
+ text.should eq(expected_output.strip)
90
+ end
91
+ end
92
+
93
+ describe "aweber escaping" do
94
+ it "should not escape aweber markup if using aweber extension" do
95
+ html = <<-eos
96
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
97
+ <html>
98
+ <body>
99
+ <p>{!date dayname+7}</p>
100
+ </body>
101
+ </html>
102
+ eos
103
+
104
+ run_in_fixture_dir("with_config") do
105
+ processor = HtmlEmailCreator::Processor.new(html)
106
+ processor.to_html.should include("<p>{!date dayname+7}</p>")
107
+ processor.to_plain_text.should include("{!date dayname+7}")
108
+ end
109
+ end
110
+ end
111
+ end