html_email_creator 1.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.
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