bootstrap-email 1.0.0.alpha3 → 1.0.1
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 +4 -4
- data/VERSION +1 -1
- data/core/bootstrap-head.scss +91 -15
- data/core/scss/components/_grid.scss +25 -20
- data/core/scss/components/_stack.scss +18 -12
- data/core/scss/utilities/_valign.scss +1 -1
- data/lib/bootstrap-email/compiler.rb +8 -7
- data/lib/bootstrap-email/converters/align.rb +2 -2
- data/lib/bootstrap-email/converters/base.rb +3 -2
- data/lib/bootstrap-email/converters/force_encoding.rb +5 -7
- data/lib/bootstrap-email/converters/grid.rb +4 -1
- data/lib/bootstrap-email/converters/margin.rb +2 -2
- data/lib/bootstrap-email/converters/padding.rb +4 -4
- data/lib/bootstrap-email/converters/stack.rb +6 -6
- data/lib/bootstrap-email.rb +0 -1
- metadata +4 -5
- data/lib/bootstrap-email/initialize.rb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3a9b2ebe28846362e698e13641ff407acd7419fa1cf578bf52702b616f80c1f
|
4
|
+
data.tar.gz: d87d15ba04e2f789be9ab51577ff17ff9ae2cd2f9b8fbe6ab0e8ad1515de870c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a73433c6c50b383c3892b53277c7f97e083ace4edac30563e138c95e878bf86928748246ebc6212e93b606ce1df15dd1c3d9320deb238e42ecff68235c30e3a2
|
7
|
+
data.tar.gz: eaf6bf4300bde849a713d4842784d8cd906ca2d256db0b548a99dfb5ce02a0da7384bd1aeff961b7a013dc928f5c886579edd4d43851a4b0c302e0d70b32ffe4
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.
|
1
|
+
1.0.1
|
data/core/bootstrap-head.scss
CHANGED
@@ -8,6 +8,11 @@
|
|
8
8
|
@import 'scss/selectors_for_utils';
|
9
9
|
@import 'scss/helper_groups';
|
10
10
|
|
11
|
+
// Force base font in Outlook
|
12
|
+
body, table, td {
|
13
|
+
font-family: $font-family-base !important;
|
14
|
+
}
|
15
|
+
|
11
16
|
// Forces Outlook.com to display emails at full width
|
12
17
|
.ExternalClass {
|
13
18
|
width: 100%;
|
@@ -66,18 +71,60 @@ table:not([class^=s-]) {
|
|
66
71
|
/*! allow_purge_after */
|
67
72
|
|
68
73
|
@media screen and (max-width: 600px) {
|
74
|
+
// Row Gap
|
75
|
+
@each $space, $value in $spacers {
|
76
|
+
.gap-#{$space}.row,
|
77
|
+
.gap-x-#{$space}.row {
|
78
|
+
margin-right: -1 * $value !important;
|
79
|
+
& > table > tbody > tr > td {
|
80
|
+
padding-right: $value !important;
|
81
|
+
}
|
82
|
+
}
|
83
|
+
.gap-#{$space}.row,
|
84
|
+
.gap-y-#{$space}.row {
|
85
|
+
margin-bottom: -1 * $value !important;
|
86
|
+
& > table > tbody > tr > td {
|
87
|
+
padding-bottom: $value !important;
|
88
|
+
}
|
89
|
+
}
|
90
|
+
}
|
91
|
+
.row.row-responsive {
|
92
|
+
margin-right: 0 !important;
|
93
|
+
}
|
94
|
+
|
95
|
+
// Stack Gap
|
96
|
+
@each $space, $value in $spacers {
|
97
|
+
table.gap-lg-#{$space}.stack-x > tbody > tr > td {
|
98
|
+
padding-right: 0 !important;
|
99
|
+
}
|
100
|
+
table.gap-lg-#{$space}.stack-y > tbody > tr > td {
|
101
|
+
padding-bottom: 0 !important;
|
102
|
+
}
|
103
|
+
}
|
104
|
+
@each $space, $value in $spacers {
|
105
|
+
table.gap-#{$space}.stack-x > tbody > tr > td {
|
106
|
+
padding-right: $value !important;
|
107
|
+
}
|
108
|
+
table.gap-#{$space}.stack-y > tbody > tr > td {
|
109
|
+
padding-bottom: $value !important;
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
69
113
|
// Grid
|
70
114
|
@each $key, $value in $grid-cols {
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
padding-left: 0 !important;
|
77
|
-
padding-right: 0 !important;
|
78
|
-
}
|
115
|
+
td.col-lg-#{$key} {
|
116
|
+
display: block;
|
117
|
+
width: 100% !important;
|
118
|
+
padding-left: 0 !important;
|
119
|
+
padding-right: 0 !important;
|
79
120
|
}
|
80
121
|
}
|
122
|
+
td.col-lg {
|
123
|
+
display: block;
|
124
|
+
width: 100% !important;
|
125
|
+
padding-left: 0 !important;
|
126
|
+
padding-right: 0 !important;
|
127
|
+
}
|
81
128
|
|
82
129
|
// Display
|
83
130
|
@each $display in $display-type {
|
@@ -91,26 +138,56 @@ table:not([class^=s-]) {
|
|
91
138
|
}
|
92
139
|
}
|
93
140
|
|
94
|
-
// Sizing
|
141
|
+
// Sizing Max Width / Height
|
142
|
+
@each $name, $property in $sizing-types {
|
143
|
+
@include sizing-util('.max-#{$name}-lg-full') {
|
144
|
+
max-#{$property}: unset !important;
|
145
|
+
#{$property}: auto !important;
|
146
|
+
}
|
147
|
+
@each $size, $value in $sizing {
|
148
|
+
@include sizing-util('.max-#{$name}-lg-#{$size}') {
|
149
|
+
max-#{$property}: unset !important;
|
150
|
+
#{$property}: auto !important;
|
151
|
+
}
|
152
|
+
}
|
153
|
+
}
|
154
|
+
@each $name, $property in $sizing-types {
|
155
|
+
@include sizing-util('.max-#{$name}-full') {
|
156
|
+
max-#{$property}: 100% !important;
|
157
|
+
#{$property}: 100% !important;
|
158
|
+
}
|
159
|
+
@each $size, $value in $sizing {
|
160
|
+
@include sizing-util('.max-#{$name}-#{$size}') {
|
161
|
+
max-#{$property}: $value !important;
|
162
|
+
#{$property}: 100% !important;
|
163
|
+
}
|
164
|
+
}
|
165
|
+
}
|
166
|
+
|
167
|
+
// Sizing Width / Height
|
95
168
|
@each $name, $property in $sizing-types {
|
96
169
|
@include sizing-util('.#{$name}-lg-full') {
|
97
|
-
|
170
|
+
#{$property}: auto !important;
|
171
|
+
}
|
172
|
+
@include sizing-util('.#{$name}-lg-auto') {
|
98
173
|
#{$property}: auto !important;
|
99
174
|
}
|
100
175
|
@each $size, $value in $sizing {
|
101
176
|
@include sizing-util('.#{$name}-lg-#{$size}') {
|
102
|
-
max-#{$property}: auto !important;
|
103
177
|
#{$property}: auto !important;
|
104
178
|
}
|
105
179
|
}
|
180
|
+
}
|
181
|
+
@each $name, $property in $sizing-types {
|
106
182
|
@include sizing-util('.#{$name}-full') {
|
107
|
-
max-#{$property}: 100% !important;
|
108
183
|
#{$property}: 100% !important;
|
109
184
|
}
|
185
|
+
@include sizing-util('.#{$name}-auto') {
|
186
|
+
#{$property}: auto !important;
|
187
|
+
}
|
110
188
|
@each $size, $value in $sizing {
|
111
189
|
@include sizing-util('.#{$name}-#{$size}') {
|
112
|
-
|
113
|
-
#{$property}: 100% !important;
|
190
|
+
#{$property}: $value !important;
|
114
191
|
}
|
115
192
|
}
|
116
193
|
}
|
@@ -132,7 +209,6 @@ table:not([class^=s-]) {
|
|
132
209
|
line-height: 0 !important;
|
133
210
|
height: 0 !important;
|
134
211
|
}
|
135
|
-
|
136
212
|
@each $size, $value in $spacers {
|
137
213
|
@include spacer-util('.s-#{$size}') {
|
138
214
|
font-size: $value !important;
|
@@ -1,13 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
.row {
|
2
|
+
margin-right: -24px;
|
3
|
+
& > table {
|
4
|
+
table-layout: fixed;
|
5
|
+
-premailer-width: 100%;
|
6
|
+
width: 100%;
|
7
|
+
& > tbody > tr > td {
|
8
|
+
min-height: 1px;
|
9
|
+
font-weight: normal;
|
10
|
+
padding-right: 24px;
|
11
|
+
vertical-align: top;
|
12
|
+
text-align: left;
|
13
|
+
}
|
11
14
|
}
|
12
15
|
}
|
13
16
|
|
@@ -19,19 +22,21 @@ table.row {
|
|
19
22
|
}
|
20
23
|
|
21
24
|
@each $space, $value in $spacers {
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
.row.gap-#{$space},
|
26
|
+
.row.gap-x-#{$space},
|
27
|
+
.row.gap-lg-#{$space},
|
28
|
+
.row.gap-x-lg-#{$space} {
|
29
|
+
margin-right: -1 * $value;
|
30
|
+
& > table > tbody > tr > td {
|
27
31
|
padding-right: $value;
|
28
32
|
}
|
29
33
|
}
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
34
|
+
.row.gap-#{$space},
|
35
|
+
.row.gap-y-#{$space},
|
36
|
+
.row.gap-lg-#{$space},
|
37
|
+
.row.gap-y-lg-#{$space} {
|
38
|
+
margin-bottom: -1 * $value;
|
39
|
+
& > table > tbody > tr > td {
|
35
40
|
padding-bottom: $value;
|
36
41
|
}
|
37
42
|
}
|
@@ -1,16 +1,22 @@
|
|
1
1
|
@each $space, $value in $spacers {
|
2
|
-
table.stack-
|
3
|
-
|
4
|
-
|
5
|
-
padding-right:
|
2
|
+
table.stack-row.gap-#{$space},
|
3
|
+
table.stack-row.gap-lg-#{$space} {
|
4
|
+
& > tbody > tr > td {
|
5
|
+
padding-right: $value;
|
6
|
+
&:last-child {
|
7
|
+
padding-right: 0;
|
8
|
+
}
|
6
9
|
}
|
7
10
|
}
|
8
|
-
table.stack-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
table.stack-col.gap-#{$space},
|
12
|
+
table.stack-col.gap-lg-#{$space} {
|
13
|
+
& > tbody > tr {
|
14
|
+
& > td {
|
15
|
+
padding-bottom: $value;
|
16
|
+
}
|
17
|
+
&:last-child > td {
|
18
|
+
padding-bottom: 0;
|
19
|
+
}
|
14
20
|
}
|
15
21
|
}
|
16
22
|
}
|
@@ -21,13 +27,13 @@
|
|
21
27
|
}
|
22
28
|
|
23
29
|
@each $align in $vertical-align {
|
24
|
-
table.stack-
|
30
|
+
table.stack-ay-#{$align} > tbody > tr > td {
|
25
31
|
vertical-align: $align;
|
26
32
|
}
|
27
33
|
}
|
28
34
|
|
29
35
|
@each $align in $text-align {
|
30
|
-
table.stack-
|
36
|
+
table.stack-ax-#{$align} > tbody > tr > td {
|
31
37
|
text-align: $align;
|
32
38
|
}
|
33
39
|
}
|
@@ -48,12 +48,15 @@ module BootstrapEmail
|
|
48
48
|
html,
|
49
49
|
with_html_string: true,
|
50
50
|
preserve_reset: false,
|
51
|
+
adapter: :nokogiri_fast,
|
52
|
+
output_encoding: 'US-ASCII',
|
51
53
|
css_string: css_string
|
52
54
|
)
|
53
55
|
self.doc = premailer.doc
|
54
56
|
end
|
55
57
|
|
56
58
|
def compile_html!
|
59
|
+
BootstrapEmail::Converter::Body.build(doc)
|
57
60
|
BootstrapEmail::Converter::Block.build(doc)
|
58
61
|
|
59
62
|
BootstrapEmail::Converter::Button.build(doc)
|
@@ -65,17 +68,15 @@ module BootstrapEmail
|
|
65
68
|
BootstrapEmail::Converter::Grid.build(doc)
|
66
69
|
BootstrapEmail::Converter::Stack.build(doc)
|
67
70
|
|
71
|
+
BootstrapEmail::Converter::Color.build(doc)
|
68
72
|
BootstrapEmail::Converter::Spacing.build(doc)
|
69
|
-
BootstrapEmail::Converter::Padding.build(doc)
|
70
73
|
BootstrapEmail::Converter::Margin.build(doc)
|
71
74
|
BootstrapEmail::Converter::Spacer.build(doc)
|
72
|
-
|
73
|
-
BootstrapEmail::Converter::Table.build(doc)
|
74
|
-
BootstrapEmail::Converter::Body.build(doc)
|
75
75
|
BootstrapEmail::Converter::Align.build(doc)
|
76
|
-
BootstrapEmail::Converter::
|
76
|
+
BootstrapEmail::Converter::Padding.build(doc)
|
77
77
|
|
78
78
|
BootstrapEmail::Converter::PreviewText.build(doc)
|
79
|
+
BootstrapEmail::Converter::Table.build(doc)
|
79
80
|
end
|
80
81
|
|
81
82
|
def inline_css!
|
@@ -83,13 +84,13 @@ module BootstrapEmail
|
|
83
84
|
end
|
84
85
|
|
85
86
|
def configure_html!
|
86
|
-
BootstrapEmail::Converter::ForceEncoding.build(doc)
|
87
87
|
BootstrapEmail::Converter::HeadStyle.build(doc)
|
88
88
|
BootstrapEmail::Converter::VersionComment.build(doc)
|
89
89
|
end
|
90
90
|
|
91
91
|
def finalize_document!
|
92
|
-
html =
|
92
|
+
html = doc.to_html(encoding: 'US-ASCII')
|
93
|
+
html = BootstrapEmail::Converter::ForceEncoding.replace(html)
|
93
94
|
case type
|
94
95
|
when :rails
|
95
96
|
(@mail.html_part || @mail).body = html
|
@@ -3,7 +3,7 @@ module BootstrapEmail
|
|
3
3
|
class Align < Base
|
4
4
|
def build
|
5
5
|
['left', 'center', 'right'].each do |type|
|
6
|
-
full_type = "
|
6
|
+
full_type = "ax-#{type}"
|
7
7
|
each_node(".#{full_type}") do |node|
|
8
8
|
align_helper(node, full_type, type)
|
9
9
|
end
|
@@ -12,7 +12,7 @@ module BootstrapEmail
|
|
12
12
|
|
13
13
|
def align_helper(node, full_type, type)
|
14
14
|
unless table?(node) || td?(node)
|
15
|
-
node['class'] = node['class'].sub(full_type, '')
|
15
|
+
node['class'] = node['class'].sub(full_type, '').strip
|
16
16
|
node = node.replace(template('table', classes: full_type, contents: node.to_html))[0]
|
17
17
|
end
|
18
18
|
node['align'] = type
|
@@ -14,7 +14,8 @@ module BootstrapEmail
|
|
14
14
|
private
|
15
15
|
|
16
16
|
def template(file, locals_hash = {})
|
17
|
-
locals_hash[:classes] = locals_hash[:classes].split.join(' ')
|
17
|
+
locals_hash[:classes] = locals_hash[:classes].to_s.split.join(' ')
|
18
|
+
locals_hash[:content] ||= nil
|
18
19
|
if @cached_templates[file]
|
19
20
|
string = @cached_templates[file]
|
20
21
|
else
|
@@ -35,7 +36,7 @@ module BootstrapEmail
|
|
35
36
|
|
36
37
|
def add_class(node, class_name)
|
37
38
|
node['class'] ||= ''
|
38
|
-
node['class']
|
39
|
+
node['class'] = "#{node['class'].strip} #{class_name}".strip
|
39
40
|
end
|
40
41
|
|
41
42
|
def margin?(node)
|
@@ -1,15 +1,13 @@
|
|
1
1
|
module BootstrapEmail
|
2
2
|
module Converter
|
3
3
|
class ForceEncoding < Base
|
4
|
-
def build
|
5
|
-
body = doc.at_css('body')
|
6
|
-
body.add_child('<force-encoding></force-encoding>')
|
7
|
-
end
|
8
|
-
|
9
4
|
def self.replace(html)
|
10
5
|
# force utf-8 character encoded in iOS Mail: https://github.com/bootstrap-email/bootstrap-email/issues/50
|
11
|
-
# this needs to be done after the document has been outputted to a string so it doesn't get converted
|
12
|
-
html.sub(
|
6
|
+
# this needs to be done after the document has been outputted to a ascii string so it doesn't get converted
|
7
|
+
html.sub(
|
8
|
+
'<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">',
|
9
|
+
'<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'
|
10
|
+
)
|
13
11
|
end
|
14
12
|
end
|
15
13
|
end
|
@@ -3,7 +3,10 @@ module BootstrapEmail
|
|
3
3
|
class Grid < Base
|
4
4
|
def build
|
5
5
|
each_node('.row') do |node|
|
6
|
-
node.
|
6
|
+
if node.at("./*[contains(@class, 'col-lg-')]")
|
7
|
+
add_class(node, 'row-responsive')
|
8
|
+
end
|
9
|
+
node.replace(template('div', classes: node['class'], contents: template('table-to-tr', contents: node.inner_html)))
|
7
10
|
end
|
8
11
|
each_node('*[class*=col]') do |node|
|
9
12
|
node.replace(template('td', classes: node['class'], contents: node.inner_html))
|
@@ -2,10 +2,10 @@ module BootstrapEmail
|
|
2
2
|
module Converter
|
3
3
|
class Margin < Base
|
4
4
|
def build
|
5
|
-
each_node('*[class*=my-], *[class*=mt-], *[class*=mb-]
|
5
|
+
each_node("*[class^='my-'], *[class^='mt-'], *[class^='mb-'], *[class*=' my-'], *[class*=' mt-'], *[class*=' mb-']") do |node|
|
6
6
|
top_class = node['class'][/m[ty]{1}-(lg-)?(\d+)/]
|
7
7
|
bottom_class = node['class'][/m[by]{1}-(lg-)?(\d+)/]
|
8
|
-
node['class'] = node['class'].gsub(/(m[tby]{1}-(lg-)?\d+)/, '')
|
8
|
+
node['class'] = node['class'].gsub(/(m[tby]{1}-(lg-)?\d+)/, '').strip
|
9
9
|
html = ''
|
10
10
|
if top_class
|
11
11
|
html += template('div', classes: "s-#{top_class.gsub(/m[ty]{1}-/, '')}", contents: nil)
|
@@ -2,12 +2,12 @@ module BootstrapEmail
|
|
2
2
|
module Converter
|
3
3
|
class Padding < Base
|
4
4
|
def build
|
5
|
-
each_node(
|
5
|
+
each_node("*[class^=p-], *[class^=pt-], *[class^=pr-], *[class^=pb-], *[class^=pl-], *[class^=px-], *[class^=py-], *[class*=' p-'], *[class*=' pt-'], *[class*=' pr-'], *[class*=' pb-'], *[class*=' pl-'], *[class*=' px-'], *[class*=' py-']") do |node|
|
6
6
|
next if ['table', 'td', 'a'].include?(node.name)
|
7
7
|
|
8
|
-
padding_regex = /(p[trblxy]
|
9
|
-
classes = node['class'].
|
10
|
-
node['class'] = node['class'].gsub(padding_regex, '')
|
8
|
+
padding_regex = /(p[trblxy]?-(lg-)?\d+)/
|
9
|
+
classes = node['class'].gsub(padding_regex).to_a.join(' ')
|
10
|
+
node['class'] = node['class'].gsub(padding_regex, '').strip
|
11
11
|
node.replace(template('table', classes: classes, contents: node.to_html))
|
12
12
|
end
|
13
13
|
end
|
@@ -2,12 +2,12 @@ module BootstrapEmail
|
|
2
2
|
module Converter
|
3
3
|
class Stack < Base
|
4
4
|
def build
|
5
|
-
|
6
|
-
|
5
|
+
stack_row
|
6
|
+
stack_col
|
7
7
|
end
|
8
8
|
|
9
|
-
def
|
10
|
-
each_node('.stack-
|
9
|
+
def stack_row
|
10
|
+
each_node('.stack-row') do |node|
|
11
11
|
html = ''
|
12
12
|
node.xpath('./*').each do |child|
|
13
13
|
html += template('td', classes: 'stack-cell', contents: child.to_html)
|
@@ -16,8 +16,8 @@ module BootstrapEmail
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
each_node('.stack-
|
19
|
+
def stack_col
|
20
|
+
each_node('.stack-col') do |node|
|
21
21
|
html = ''
|
22
22
|
node.xpath('./*').each do |child|
|
23
23
|
html += template('tr', classes: 'stack-cell', contents: child.to_html)
|
data/lib/bootstrap-email.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bootstrap-email
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stuart Yamartino
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -129,7 +129,6 @@ files:
|
|
129
129
|
- lib/bootstrap-email/converters/table.rb
|
130
130
|
- lib/bootstrap-email/converters/version_comment.rb
|
131
131
|
- lib/bootstrap-email/erb.rb
|
132
|
-
- lib/bootstrap-email/initialize.rb
|
133
132
|
- lib/bootstrap-email/rails/action_mailer.rb
|
134
133
|
- lib/bootstrap-email/rails/engine.rb
|
135
134
|
- lib/bootstrap-email/sass_cache.rb
|
@@ -150,9 +149,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
150
149
|
version: '2.0'
|
151
150
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
151
|
requirements:
|
153
|
-
- - "
|
152
|
+
- - ">="
|
154
153
|
- !ruby/object:Gem::Version
|
155
|
-
version:
|
154
|
+
version: '0'
|
156
155
|
requirements: []
|
157
156
|
rubygems_version: 3.0.3
|
158
157
|
signing_key:
|
@@ -1 +0,0 @@
|
|
1
|
-
Premailer::Adapter.use = :nokogiri_fast
|