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

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