bootstrap-email 0.0.0.alpha.1 → 0.0.0.alpha.2

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: 79e15e6409d62b631a967453b3cc832fcbedf62a
4
- data.tar.gz: 3b1777952a01a26d3eb37a131bff5952f5d61ed3
3
+ metadata.gz: d697ca73b6f0d8dd482151f4fefb5362100bf574
4
+ data.tar.gz: 98fdfe5fe8d602cf595750bdad3a123799667db6
5
5
  SHA512:
6
- metadata.gz: fba52120dc88c83ce84f8c91913c4e73d5d71bd12ad9d1f1479a9509352c5e8c7c48a714c2ae65317632fb36aa85a6250e5637f1d9cb555e02d916b2298fe10f
7
- data.tar.gz: f2143b72a89bb7e08d957a61a87b09cb4b3d97a59bebe99bdad3da6dead48bb865da09e133d5df8ed9bdf3c88bf3c55ec9b78bfdc75a553546859006d3bc8d3f
6
+ metadata.gz: 6d2fc92efb6f6c04e261e3d306dc488c17ef0f17f40b686409b5a58c2d918acf3cd262352063c840880774285597f7222abfe17d178935247979d68258f3e4e4
7
+ data.tar.gz: 79aa08506d89efbc8856f15fde6e306e7c38ca5957065fa9a95373e467d3a8abe5097c253b0d11b438d8ce718236481a8433052198fac8aa6beac6ddffc8ed62
@@ -1,13 +1,152 @@
1
1
  require 'nokogiri'
2
2
  require 'erb'
3
3
  require 'ostruct'
4
- require 'active-mailer'
4
+ require 'action_mailer'
5
5
  require 'premailer'
6
+ require 'premailer/rails'
7
+ require 'rails'
6
8
 
7
- Premailer::Rails.config.merge!(adapter: :nokogiri)
9
+ module BootstrapEmail
10
+ class Compiler
8
11
 
12
+ def initialize mail
13
+ @mail = mail
14
+ @doc = Nokogiri::HTML(@mail.body.raw_source)
15
+ end
9
16
 
10
- require 'bootstrap-email/bootstrap-email'
11
- require 'bootstrap-email/active-mailer'
17
+ def compile_html!
18
+ button
19
+ badge
20
+ alert
21
+ align
22
+ card
23
+ hr
24
+ container
25
+ grid
26
+ padding
27
+ margin
28
+ table
29
+ end
30
+
31
+ def update_mailer!
32
+ @mail.body = @doc.to_html
33
+ @mail
34
+ end
35
+
36
+ private
37
+
38
+ def build_from_template template, locals_hash = {}
39
+ namespace = OpenStruct.new(locals_hash)
40
+ template = File.open(File.expand_path("../core/templates/#{template}.html.erb", __dir__)).read
41
+ Nokogiri::HTML::DocumentFragment.parse(ERB.new(template).result(namespace.instance_eval { binding }))
42
+ end
43
+
44
+ def each_node css_lookup, &blk
45
+ # sort by youngest child and traverse backwards up the tree
46
+ @doc.css(css_lookup).sort_by{ |n| n.ancestors.size }.reverse!.each(&blk)
47
+ end
48
+
49
+ def button
50
+ each_node('.btn') do |node| # move all classes up and remove all classes from the element
51
+ node.replace(build_from_template('table-left', {classes: node['class'], contents: node.delete('class') && node.to_html}))
52
+ end
53
+ end
54
+
55
+ def badge
56
+ each_node('.badge') do |node| # move all classes up and remove all classes from the element
57
+ node.replace(build_from_template('table-left', {classes: node['class'], contents: node.delete('class') && node.to_html}))
58
+ end
59
+ end
60
+
61
+ def alert
62
+ each_node('.alert') do |node| # move all classes up and remove all classes from the element
63
+ node.replace(build_from_template('table', {classes: node['class'], contents: node.delete('class') && node.to_html}))
64
+ end
65
+ end
66
+
67
+ def align
68
+ each_node('.align-left') do |node| # align table and move contents
69
+ node['class'] = node['class'].sub(/align-left/, '')
70
+ node.replace(build_from_template('align-left', {contents: node.to_html}))
71
+ end
72
+ each_node('.align-center') do |node| # align table and move contents
73
+ node['class'] = node['class'].sub(/align-center/, '')
74
+ node.replace(build_from_template('align-center', {contents: node.to_html}))
75
+ end
76
+ each_node('.align-right') do |node| # align table and move contents
77
+ node['class'] = node['class'].sub(/align-right/, '')
78
+ node.replace(build_from_template('align-right', {contents: node.to_html}))
79
+ end
80
+ end
81
+
82
+ def card
83
+ each_node('.card') do |node| # move all classes up and remove all classes from element
84
+ node.replace(build_from_template('table', {classes: node['class'], contents: node.delete('class') && node.to_html}))
85
+ end
86
+ each_node('.card-body') do |node| # move all classes up and remove all classes from element
87
+ node.replace(build_from_template('table', {classes: node['class'], contents: node.delete('class') && node.to_html}))
88
+ end
89
+ end
90
+
91
+ def hr
92
+ each_node('hr') do |node| # drop hr in place of current
93
+ node.replace(build_from_template('hr', {classes: "hr #{node['class']}"}))
94
+ end
95
+ end
96
+
97
+ def container
98
+ each_node('.container') do |node|
99
+ node.replace(build_from_template('container', {classes: node['class'], contents: node.inner_html}))
100
+ end
101
+ each_node('.container-fluid') do |node|
102
+ node.replace(build_from_template('table', {classes: node['class'], contents: node.inner_html}))
103
+ end
104
+ end
105
+
106
+ def grid
107
+ each_node('.row') do |node|
108
+ node.replace(build_from_template('row', {classes: node['class'], contents: node.inner_html}))
109
+ end
110
+ each_node('*[class*=col]') do |node|
111
+ node.replace(build_from_template('col', {classes: node['class'], contents: node.inner_html}))
112
+ end
113
+ end
114
+
115
+ def padding
116
+ each_node('*[class*=p-], *[class*=pt-], *[class*=pr-], *[class*=pb-], *[class*=pl-], *[class*=px-], *[class*=py-]') do |node|
117
+ if node.name != 'table' # if it is already on a table, set the padding on the table, else wrap the content in a table
118
+ padding_regex = /(p[trblxy]?-\d)/
119
+ classes = node['class'].scan(padding_regex).join(' ')
120
+ node['class'] = node['class'].sub(padding_regex, '')
121
+ node.replace(build_from_template('table', {classes: classes, contents: node.to_html}))
122
+ end
123
+ end
124
+ end
125
+
126
+ def margin
127
+ each_node('*[class*=m-], *[class*=mt-], *[class*=mr-], *[class*=mb-], *[class*=ml-], *[class*=mx-], *[class*=my-]') do |node|
128
+ if node.name != 'div' # if it is already on a div, set the margin on the div, else wrap the content in a div
129
+ margin_regex = /(m[trblxy]?-\d)/
130
+ classes = node['class'].scan(margin_regex).join(' ')
131
+ node['class'] = node['class'].sub(margin_regex, '')
132
+ node.replace(build_from_template('div', {classes: classes, contents: node.to_html}))
133
+ end
134
+ end
135
+ end
136
+
137
+ def table
138
+ @doc.css('table').each do |node|
139
+ #border="0" cellpadding="0" cellspacing="0"
140
+ node['border'] = 0
141
+ node['cellpadding'] = 0
142
+ node['cellspacing'] = 0
143
+ end
144
+ end
145
+
146
+ end
147
+ end
148
+
149
+ require 'bootstrap-email/premailer_railtie'
150
+ require 'bootstrap-email/action_mailer'
12
151
  require 'bootstrap-email/engine'
13
152
  require 'bootstrap-email/version'
@@ -1,20 +1,22 @@
1
1
  class ActionMailer::Base
2
- helper BootstrapEmailHelper
3
2
 
3
+ # sit in the middle and compile the html
4
4
  def bootstrap_mail *args
5
- mail = mail(*args)
6
- bootstrap = BootstrapEmail.new(mail)
7
- bootstrap.compiled_html!
5
+ bootstrap = BootstrapEmail::Compiler.new(mail(*args))
6
+ bootstrap.compile_html!
7
+ bootstrap.update_mailer!
8
8
  end
9
- end
10
9
 
11
- module BootstrapEmailHelper
12
-
13
- def bootstrap_email_head
14
- <<-HEREDOC
15
- <style>
16
- #{File.open('../../core/sass/head.scss').read}
17
- </style>
18
- HEREDOC
10
+ # helper to inject style tags into head of the email template
11
+ module BootstrapEmailHelper
12
+ def bootstrap_email_head
13
+ html_string = <<-HEREDOC
14
+ <style type="text/css" data-premailer="ignore">
15
+ #{File.open(File.expand_path('../../core/head.css', __dir__)).read}
16
+ </style>
17
+ HEREDOC
18
+ html_string.html_safe
19
+ end
19
20
  end
21
+ helper BootstrapEmailHelper
20
22
  end
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
2
  module Rails
3
- VERSION = '0.0.0.alpha.1'
3
+ VERSION = '0.0.0.alpha.2'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bootstrap-email
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0.alpha.1
4
+ version: 0.0.0.alpha.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stuart Yamartino
@@ -26,33 +26,59 @@ dependencies:
26
26
  version: '1.9'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: actionmailer
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - ">="
32
46
  - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
47
+ version: '3'
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: '6'
51
+ type: :runtime
35
52
  prerelease: false
36
53
  version_requirements: !ruby/object:Gem::Requirement
37
54
  requirements:
38
55
  - - ">="
39
56
  - !ruby/object:Gem::Version
40
- version: '0'
57
+ version: '3'
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '6'
41
61
  - !ruby/object:Gem::Dependency
42
- name: actionmailer
62
+ name: rails
43
63
  requirement: !ruby/object:Gem::Requirement
44
64
  requirements:
45
65
  - - ">="
46
66
  - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
67
+ version: '3'
68
+ - - "<"
69
+ - !ruby/object:Gem::Version
70
+ version: '6'
71
+ type: :runtime
49
72
  prerelease: false
50
73
  version_requirements: !ruby/object:Gem::Requirement
51
74
  requirements:
52
75
  - - ">="
53
76
  - !ruby/object:Gem::Version
54
- version: '0'
55
- description: Bootstrap 4 style sheet and compiler for responsive and consistent emails.
77
+ version: '3'
78
+ - - "<"
79
+ - !ruby/object:Gem::Version
80
+ version: '6'
81
+ description:
56
82
  email: stuartyamartino@gmail.com
57
83
  executables: []
58
84
  extensions: []
@@ -60,10 +86,9 @@ extra_rdoc_files: []
60
86
  files:
61
87
  - lib/bootstrap-email.rb
62
88
  - lib/bootstrap-email/action_mailer.rb
63
- - lib/bootstrap-email/bootstrap_email.rb
64
89
  - lib/bootstrap-email/engine.rb
65
90
  - lib/bootstrap-email/version.rb
66
- homepage: http://rubygems.org/gems/bootstrap-email
91
+ homepage: https://github.com/stuyam/bootstrap-email
67
92
  licenses:
68
93
  - MIT
69
94
  metadata: {}
@@ -73,9 +98,9 @@ require_paths:
73
98
  - lib
74
99
  required_ruby_version: !ruby/object:Gem::Requirement
75
100
  requirements:
76
- - - ">="
101
+ - - "~>"
77
102
  - !ruby/object:Gem::Version
78
- version: '0'
103
+ version: '2.0'
79
104
  required_rubygems_version: !ruby/object:Gem::Requirement
80
105
  requirements:
81
106
  - - ">"
@@ -86,5 +111,6 @@ rubyforge_project:
86
111
  rubygems_version: 2.6.8
87
112
  signing_key:
88
113
  specification_version: 4
89
- summary: Bootstrap 4 style sheet and compiler for responsive and consistent emails.
114
+ summary: Bootstrap 4 stylesheet, compiler, and inliner for responsive and consistent
115
+ emails with the Bootstrap syntax you know and love.
90
116
  test_files: []
@@ -1,75 +0,0 @@
1
- class BootstrapEmail
2
-
3
- def constructor mail
4
- @mail = mail
5
- end
6
-
7
- def compiled_html!
8
- doc = Nokogiri::HTML(@mail.body.raw_source)
9
- doc.css('.btn').each do |node| # move all classes up and remove all classes from the element
10
- node.replace(build_from_template('table-left', {classes: node['class'], contents: node.delete('class') && node.to_html}))
11
- end
12
- doc.css('.badge').each do |node| # move all classes up and remove all classes from the element
13
- node.replace(build_from_template('table-left', {classes: node['class'], contents: node.delete('class') && node.to_html}))
14
- end
15
- doc.css('.alert').each do |node| # move all classes up and remove all classes from the element
16
- node.replace(build_from_template('table', {classes: node['class'], contents: node.delete('class') && node.to_html}))
17
- end
18
- doc.css('.align-left').each do |node| # align table and move contents
19
- node.replace(build_from_template('align-left', {contents: node.to_html}))
20
- end
21
- doc.css('.align-center').each do |node| # align table and move contents
22
- node.replace(build_from_template('align-center', {contents: node.to_html}))
23
- end
24
- doc.css('.align-right').each do |node| # align table and move contents
25
- node.replace(build_from_template('align-right', {contents: node.to_html}))
26
- end
27
- doc.css('.card').each do |node| # move all classes up and remove all classes from element
28
- node.replace(build_from_template('table', {classes: node['class'], contents: node.delete('class') && node.to_html}))
29
- end
30
- doc.css('.card-body').each do |node| # move all classes up and remove all classes from element
31
- node.replace(build_from_template('table', {classes: node['class'], contents: node.delete('class') && node.to_html}))
32
- end
33
- doc.css('hr').each do |node| # drop hr in place of current
34
- node.replace(build_from_template('hr'))
35
- end
36
- doc.css('.container').each do |node|
37
- node.replace(build_from_template('container', {classes: node['class'], contents: node.inner_html}))
38
- end
39
- doc.css('.container-fluid').each do |node|
40
- node.replace(build_from_template('table', {classes: node['class'], contents: node.inner_html}))
41
- end
42
- doc.css('.row').each do |node|
43
- node.replace(build_from_template('row', {classes: node['class'], contents: node.inner_html}))
44
- end
45
- doc.css('*[class^=col]').each do |node|
46
- node.replace(build_from_template('col', {classes: node['class'], contents: node.inner_html}))
47
- end
48
- padding = %w( p- pt- pr- pb- pl- px- py- ).map{ |padding| "contains(@class, '#{padding}')" }.join(' or ')
49
- doc.xpath("//*[#{padding}]").each do |node|
50
- if node.name != 'table' # if it is already on a table, set the padding on the table, else wrap the content in a table
51
- node.replace(build_from_template('table', {classes: node['class'], contents: node.delete('class') && node.to_html}))
52
- end
53
- end
54
- margin = %w( m- mt- mr- mb- ml- mx- my- ).map{ |margin| "contains(@class, '#{margin}')" }.join(' or ')
55
- doc.xpath("//*[#{margin}]").each do |node|
56
- if node.name != 'div' # if it is already on a div, set the margin on the div, else wrap the content in a div
57
- node.replace(build_from_template('div', {classes: node['class'].scan(/(m[trblxy]?-\d)/).join(' '), contents: node.delete('class') && node.to_html}))
58
- end
59
- end
60
- doc.css('table').each do |node|
61
- #border="0" cellpadding="0" cellspacing="0"
62
- node['border'] = 0
63
- node['cellpadding'] = 0
64
- node['cellspacing'] = 0
65
- end
66
- @mail.body = doc.to_html
67
- @mail
68
- end
69
-
70
- def build_from_template template, locals_hash = {}
71
- namespace = OpenStruct.new(locals_hash)
72
- template = File.open("../../core/templates/#{template}.html.erb").read
73
- Nokogiri::HTML::DocumentFragment.parse(ERB.new(template).result(namespace.instance_eval { binding }))
74
- end
75
- end