bootstrap-email 1.0.0.alpha2.1 → 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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/core/bootstrap-head.scss +88 -15
  4. data/core/scss/_utilities.scss +1 -1
  5. data/core/scss/components/_grid.scss +25 -20
  6. data/core/scss/components/_stack.scss +18 -12
  7. data/core/scss/utilities/_sizing.scss +4 -0
  8. data/core/scss/utilities/_valign.scss +1 -1
  9. data/core/templates/body.html +9 -0
  10. data/core/templates/{container.html.erb → container.html} +2 -2
  11. data/core/templates/div.html +3 -0
  12. data/core/templates/table-left.html +9 -0
  13. data/core/templates/table-to-tbody.html +5 -0
  14. data/core/templates/table-to-tr.html +7 -0
  15. data/core/templates/table.html +9 -0
  16. data/core/templates/td.html +3 -0
  17. data/core/templates/{tr.html.erb → tr.html} +1 -1
  18. data/lib/bootstrap-email/bootstrap_email_cli.rb +3 -4
  19. data/lib/bootstrap-email/compiler.rb +33 -28
  20. data/lib/bootstrap-email/config.rb +50 -0
  21. data/lib/bootstrap-email/{components → converters}/alert.rb +1 -1
  22. data/lib/bootstrap-email/{components → converters}/align.rb +3 -3
  23. data/lib/bootstrap-email/{components → converters}/badge.rb +1 -1
  24. data/lib/bootstrap-email/{components → converters}/base.rb +16 -7
  25. data/lib/bootstrap-email/{components → converters}/block.rb +1 -1
  26. data/lib/bootstrap-email/{components → converters}/body.rb +1 -1
  27. data/lib/bootstrap-email/{components → converters}/button.rb +1 -1
  28. data/lib/bootstrap-email/{components → converters}/card.rb +1 -1
  29. data/lib/bootstrap-email/{components → converters}/color.rb +1 -1
  30. data/lib/bootstrap-email/{components → converters}/container.rb +1 -1
  31. data/lib/bootstrap-email/converters/force_encoding.rb +14 -0
  32. data/lib/bootstrap-email/{components → converters}/grid.rb +2 -2
  33. data/lib/bootstrap-email/{components → converters}/head_style.rb +1 -1
  34. data/lib/bootstrap-email/{components → converters}/hr.rb +1 -1
  35. data/lib/bootstrap-email/{components → converters}/margin.rb +3 -3
  36. data/lib/bootstrap-email/converters/padding.rb +16 -0
  37. data/lib/bootstrap-email/{components → converters}/paragraph.rb +1 -1
  38. data/lib/bootstrap-email/{components → converters}/preview_text.rb +1 -1
  39. data/lib/bootstrap-email/{components → converters}/spacer.rb +1 -1
  40. data/lib/bootstrap-email/{components → converters}/spacing.rb +1 -1
  41. data/lib/bootstrap-email/{components → converters}/stack.rb +7 -7
  42. data/lib/bootstrap-email/{components → converters}/table.rb +1 -1
  43. data/lib/bootstrap-email/{components → converters}/version_comment.rb +1 -1
  44. data/lib/bootstrap-email/sass_cache.rb +16 -19
  45. data/lib/bootstrap-email/setup.rb +27 -0
  46. data/lib/bootstrap-email.rb +5 -3
  47. metadata +38 -37
  48. data/core/templates/body.html.erb +0 -9
  49. data/core/templates/div.html.erb +0 -3
  50. data/core/templates/table-left.html.erb +0 -9
  51. data/core/templates/table-to-tbody.html.erb +0 -5
  52. data/core/templates/table-to-tr.html.erb +0 -7
  53. data/core/templates/table.html.erb +0 -9
  54. data/core/templates/td.html.erb +0 -3
  55. data/lib/bootstrap-email/components/force_encoding.rb +0 -16
  56. data/lib/bootstrap-email/components/padding.rb +0 -16
  57. data/lib/bootstrap-email/initialize.rb +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 754525440d7ea29f8ca2fbd07a4c54af48abf49bb3a08e6be127c4b287cbb94b
4
- data.tar.gz: e6164558bc455056434601be51978b0cae979bb4581238a4325c53da493cbb4b
3
+ metadata.gz: f0363b6b03e3d4fbca8e0e52c55c2a3120671c720807fb970f96c2a711bedc60
4
+ data.tar.gz: 8462e35921bcfe274abed980d895e1ca57fc06f30d91e8c70ff15f9355175ef5
5
5
  SHA512:
6
- metadata.gz: 436b384bb50dc14c83b4d2903af0c5caeeecc3ef99e618383fb7aa05bac1ca43e0bde09619c229806ae7926adc762296ae7c70f3dfa7c7c10a79c2702a2d40e4
7
- data.tar.gz: bb4e1834510e3a833a518a559d460972637012f6e3b1771fc46238af972b8df0fcd2a1ebfbd2c5d76eedb8eaa532600e4fc9746856de670ddab4645977da8d95
6
+ metadata.gz: 50e8c9a0967f48e016b24cb8f46f92e5ff4fb3b8682b23131bea81cd73d6aec5334c6098c77ce2ecf1a811acc0f459c8feae122bfb997815fc955c2a29a4525d
7
+ data.tar.gz: 68650d469df9644d5c1c9f2ad990ee33697f297382c9f81111f5553d01a14c7071de409a82ab5353178a961397d9e496dd30aaf42b5d99b1c9e2bcb86450bbcb
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0.alpha2.1
1
+ 1.0.0
@@ -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,57 @@ 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
+
92
+ // Stack Gap
93
+ @each $space, $value in $spacers {
94
+ table.gap-lg-#{$space}.stack-x > tbody > tr > td {
95
+ padding-right: 0 !important;
96
+ }
97
+ table.gap-lg-#{$space}.stack-y > tbody > tr > td {
98
+ padding-bottom: 0 !important;
99
+ }
100
+ }
101
+ @each $space, $value in $spacers {
102
+ table.gap-#{$space}.stack-x > tbody > tr > td {
103
+ padding-right: $value !important;
104
+ }
105
+ table.gap-#{$space}.stack-y > tbody > tr > td {
106
+ padding-bottom: $value !important;
107
+ }
108
+ }
109
+
69
110
  // Grid
70
111
  @each $key, $value in $grid-cols {
71
- table.row > tbody > tr {
72
- & > td.col-lg-#{$key},
73
- & > td.col-lg {
74
- display: block;
75
- width: 100% !important;
76
- padding-left: 0 !important;
77
- padding-right: 0 !important;
78
- }
112
+ td.col-lg-#{$key} {
113
+ display: block;
114
+ width: 100% !important;
115
+ padding-left: 0 !important;
116
+ padding-right: 0 !important;
79
117
  }
80
118
  }
119
+ td.col-lg {
120
+ display: block;
121
+ width: 100% !important;
122
+ padding-left: 0 !important;
123
+ padding-right: 0 !important;
124
+ }
81
125
 
82
126
  // Display
83
127
  @each $display in $display-type {
@@ -91,26 +135,56 @@ table:not([class^=s-]) {
91
135
  }
92
136
  }
93
137
 
94
- // Sizing
138
+ // Sizing Max Width / Height
139
+ @each $name, $property in $sizing-types {
140
+ @include sizing-util('.max-#{$name}-lg-full') {
141
+ max-#{$property}: unset !important;
142
+ #{$property}: auto !important;
143
+ }
144
+ @each $size, $value in $sizing {
145
+ @include sizing-util('.max-#{$name}-lg-#{$size}') {
146
+ max-#{$property}: unset !important;
147
+ #{$property}: auto !important;
148
+ }
149
+ }
150
+ }
151
+ @each $name, $property in $sizing-types {
152
+ @include sizing-util('.max-#{$name}-full') {
153
+ max-#{$property}: 100% !important;
154
+ #{$property}: 100% !important;
155
+ }
156
+ @each $size, $value in $sizing {
157
+ @include sizing-util('.max-#{$name}-#{$size}') {
158
+ max-#{$property}: $value !important;
159
+ #{$property}: 100% !important;
160
+ }
161
+ }
162
+ }
163
+
164
+ // Sizing Width / Height
95
165
  @each $name, $property in $sizing-types {
96
166
  @include sizing-util('.#{$name}-lg-full') {
97
- max-#{$property}: auto !important;
167
+ #{$property}: auto !important;
168
+ }
169
+ @include sizing-util('.#{$name}-lg-auto') {
98
170
  #{$property}: auto !important;
99
171
  }
100
172
  @each $size, $value in $sizing {
101
173
  @include sizing-util('.#{$name}-lg-#{$size}') {
102
- max-#{$property}: auto !important;
103
174
  #{$property}: auto !important;
104
175
  }
105
176
  }
177
+ }
178
+ @each $name, $property in $sizing-types {
106
179
  @include sizing-util('.#{$name}-full') {
107
- max-#{$property}: 100% !important;
108
180
  #{$property}: 100% !important;
109
181
  }
182
+ @include sizing-util('.#{$name}-auto') {
183
+ #{$property}: auto !important;
184
+ }
110
185
  @each $size, $value in $sizing {
111
186
  @include sizing-util('.#{$name}-#{$size}') {
112
- max-#{$property}: $value !important;
113
- #{$property}: 100% !important;
187
+ #{$property}: $value !important;
114
188
  }
115
189
  }
116
190
  }
@@ -132,7 +206,6 @@ table:not([class^=s-]) {
132
206
  line-height: 0 !important;
133
207
  height: 0 !important;
134
208
  }
135
-
136
209
  @each $size, $value in $spacers {
137
210
  @include spacer-util('.s-#{$size}') {
138
211
  font-size: $value !important;
@@ -117,9 +117,9 @@ $border-widths: (
117
117
  ) !default;
118
118
 
119
119
  $border-radiuses: (
120
+ '': 4px,
120
121
  '-none': 0px,
121
122
  '-sm': 2px,
122
- '': 4px,
123
123
  '-md': 6px,
124
124
  '-lg': 8px,
125
125
  '-xl': 12px,
@@ -1,13 +1,16 @@
1
- table.row {
2
- table-layout: fixed;
3
- -premailer-width: 100%;
4
- width: 100%;
5
- & > tbody > tr > td {
6
- min-height: 1px;
7
- font-weight: normal;
8
- padding-right: 30px;
9
- vertical-align: top;
10
- text-align: left;
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
- table.row.g-#{$space},
23
- table.row.gx-#{$space},
24
- table.row.g-lg-#{$space},
25
- table.row.gx-lg-#{$space} {
26
- & > tbody > tr > td {
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
- table.row.g-#{$space},
31
- table.row.gy-#{$space},
32
- table.row.g-lg-#{$space},
33
- table.row.gy-lg-#{$space} {
34
- & > tbody > tr > td {
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-x.gap-#{$space} > tbody > tr > td {
3
- padding-right: $value;
4
- &:last-child {
5
- padding-right: 0;
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-y.gap-#{$space} > tbody > tr {
9
- & > td {
10
- padding-bottom: $value;
11
- }
12
- &:last-child > td {
13
- padding-bottom: 0;
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-valign-#{$align} > tbody > tr > td {
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-align-#{$align} > tbody > tr > td {
36
+ table.stack-ax-#{$align} > tbody > tr > td {
31
37
  text-align: $align;
32
38
  }
33
39
  }
@@ -21,6 +21,10 @@
21
21
  -premailer-#{$property}: 100%;
22
22
  #{$property}: 100%;
23
23
  }
24
+ @include sizing-util('.#{$name}-#{$prefix}auto') {
25
+ -premailer-#{$property}: auto;
26
+ #{$property}: auto;
27
+ }
24
28
  @each $size, $value in $sizing {
25
29
  @include sizing-util('.#{$name}-#{$prefix}#{$size}') {
26
30
  -premailer-#{$property}: strip-unit($value);
@@ -1,5 +1,5 @@
1
1
  @each $align in $vertical-align {
2
- @include valign-util('.valign-#{$align}') {
2
+ @include valign-util('.ay-#{$align}') {
3
3
  vertical-align: $align !important;
4
4
  }
5
5
  }
@@ -0,0 +1,9 @@
1
+ <table class="{{ classes }}" valign="top" role="presentation">
2
+ <tbody>
3
+ <tr>
4
+ <td valign="top">
5
+ {{ contents }}
6
+ </td>
7
+ </tr>
8
+ </tbody>
9
+ </table>
@@ -1,4 +1,4 @@
1
- <table class="<%= classes %>" role="presentation">
1
+ <table class="{{ classes }}" role="presentation">
2
2
  <tbody>
3
3
  <tr>
4
4
  <td align="center">
@@ -12,7 +12,7 @@
12
12
  <tbody>
13
13
  <tr>
14
14
  <td>
15
- <%= contents %>
15
+ {{ contents }}
16
16
  </td>
17
17
  </tr>
18
18
  </tbody>
@@ -0,0 +1,3 @@
1
+ <div class="{{ classes }}">
2
+ {{ contents }}
3
+ </div>
@@ -0,0 +1,9 @@
1
+ <table class="{{ classes }}" align="left" role="presentation">
2
+ <tbody>
3
+ <tr>
4
+ <td>
5
+ {{ contents }}
6
+ </td>
7
+ </tr>
8
+ </tbody>
9
+ </table>
@@ -0,0 +1,5 @@
1
+ <table class="{{ classes }}" role="presentation">
2
+ <tbody>
3
+ {{ contents }}
4
+ </tbody>
5
+ </table>
@@ -0,0 +1,7 @@
1
+ <table class="{{ classes }}" role="presentation">
2
+ <tbody>
3
+ <tr>
4
+ {{ contents }}
5
+ </tr>
6
+ </tbody>
7
+ </table>
@@ -0,0 +1,9 @@
1
+ <table class="{{ classes }}" role="presentation">
2
+ <tbody>
3
+ <tr>
4
+ <td>
5
+ {{ contents }}
6
+ </td>
7
+ </tr>
8
+ </tbody>
9
+ </table>
@@ -0,0 +1,3 @@
1
+ <td class="{{ classes }}">
2
+ {{ contents }}
3
+ </td>
@@ -1,5 +1,5 @@
1
1
  <tr>
2
2
  <td>
3
- <%= contents %>
3
+ {{ contents }}
4
4
  </td>
5
5
  </tr>
@@ -1,6 +1,5 @@
1
1
  require_relative '../bootstrap-email'
2
2
  require 'optparse'
3
- require 'fileutils'
4
3
 
5
4
  input = nil
6
5
  options = {
@@ -37,7 +36,7 @@ parser = OptionParser.new do |opts|
37
36
  options[:destination] = v
38
37
  end
39
38
 
40
- opts.on('-c', '--config STRING', String, 'Relative path to SCSS config config file to customize Bootstrap Email.') do |v|
39
+ opts.on('-c', '--config STRING', String, 'Relative path to ruby config file to customize Bootstrap Email.') do |v|
41
40
  options[:config] = File.expand_path(v, Dir.pwd)
42
41
  end
43
42
 
@@ -82,9 +81,9 @@ if input
82
81
  end
83
82
  when :file
84
83
  path = File.expand_path(input, Dir.pwd)
85
- puts BootstrapEmail::Compiler.new(path, type: :file, options: {config_path: options[:config]}).perform_full_compile
84
+ puts BootstrapEmail::Compiler.new(path, type: :file, options: {config_path: options[:config], sass_log_enabled: false}).perform_full_compile
86
85
  when :string
87
- puts BootstrapEmail::Compiler.new(input, options: {config_path: options[:config]}).perform_full_compile
86
+ puts BootstrapEmail::Compiler.new(input, options: {config_path: options[:config], sass_log_enabled: false}).perform_full_compile
88
87
  end
89
88
  else
90
89
  puts opts
@@ -3,6 +3,7 @@ module BootstrapEmail
3
3
  attr_accessor :type, :doc, :premailer
4
4
 
5
5
  def initialize(input, type: :string, options: {})
6
+ BootstrapEmail.load_options(options)
6
7
  self.type = type
7
8
  case type
8
9
  when :rails
@@ -14,7 +15,8 @@ module BootstrapEmail
14
15
  html = File.read(input)
15
16
  end
16
17
  html = add_layout!(html)
17
- build_premailer_doc(html, options)
18
+ sass_load_paths
19
+ build_premailer_doc(html)
18
20
  end
19
21
 
20
22
  def perform_full_compile
@@ -36,42 +38,45 @@ module BootstrapEmail
36
38
  )
37
39
  end
38
40
 
39
- def build_premailer_doc(html, options)
40
- SassC.load_paths << File.expand_path('../../core', __dir__)
41
- css_string = BootstrapEmail::SassCache.compile('bootstrap-email', config_path: options[:config_path], style: :expanded)
41
+ def sass_load_paths
42
+ SassC.load_paths << BootstrapEmail.config.sass_load_paths
43
+ end
44
+
45
+ def build_premailer_doc(html)
46
+ css_string = BootstrapEmail::SassCache.compile('bootstrap-email', style: :expanded)
42
47
  self.premailer = Premailer.new(
43
48
  html,
44
49
  with_html_string: true,
45
50
  preserve_reset: false,
51
+ adapter: :nokogiri_fast,
52
+ output_encoding: 'US-ASCII',
46
53
  css_string: css_string
47
54
  )
48
55
  self.doc = premailer.doc
49
56
  end
50
57
 
51
58
  def compile_html!
52
- BootstrapEmail::Component::Block.build(doc)
53
-
54
- BootstrapEmail::Component::Button.build(doc)
55
- BootstrapEmail::Component::Badge.build(doc)
56
- BootstrapEmail::Component::Alert.build(doc)
57
- BootstrapEmail::Component::Card.build(doc)
58
- # BootstrapEmail::Component::Paragraph.build(doc) this might be too much
59
- BootstrapEmail::Component::Hr.build(doc)
60
- BootstrapEmail::Component::Container.build(doc)
61
- BootstrapEmail::Component::Grid.build(doc)
62
- BootstrapEmail::Component::Stack.build(doc)
59
+ BootstrapEmail::Converter::Body.build(doc)
60
+ BootstrapEmail::Converter::Block.build(doc)
63
61
 
64
- BootstrapEmail::Component::Spacing.build(doc)
65
- BootstrapEmail::Component::Padding.build(doc)
66
- BootstrapEmail::Component::Margin.build(doc)
67
- BootstrapEmail::Component::Spacer.build(doc)
62
+ BootstrapEmail::Converter::Button.build(doc)
63
+ BootstrapEmail::Converter::Badge.build(doc)
64
+ BootstrapEmail::Converter::Alert.build(doc)
65
+ BootstrapEmail::Converter::Card.build(doc)
66
+ BootstrapEmail::Converter::Hr.build(doc)
67
+ BootstrapEmail::Converter::Container.build(doc)
68
+ BootstrapEmail::Converter::Grid.build(doc)
69
+ BootstrapEmail::Converter::Stack.build(doc)
68
70
 
69
- BootstrapEmail::Component::Table.build(doc)
70
- BootstrapEmail::Component::Body.build(doc)
71
- BootstrapEmail::Component::Align.build(doc)
72
- BootstrapEmail::Component::Color.build(doc)
71
+ BootstrapEmail::Converter::Color.build(doc)
72
+ BootstrapEmail::Converter::Spacing.build(doc)
73
+ BootstrapEmail::Converter::Margin.build(doc)
74
+ BootstrapEmail::Converter::Spacer.build(doc)
75
+ BootstrapEmail::Converter::Align.build(doc)
76
+ BootstrapEmail::Converter::Padding.build(doc)
73
77
 
74
- BootstrapEmail::Component::PreviewText.build(doc)
78
+ BootstrapEmail::Converter::PreviewText.build(doc)
79
+ BootstrapEmail::Converter::Table.build(doc)
75
80
  end
76
81
 
77
82
  def inline_css!
@@ -79,13 +84,13 @@ module BootstrapEmail
79
84
  end
80
85
 
81
86
  def configure_html!
82
- BootstrapEmail::Component::ForceEncoding.build(doc)
83
- BootstrapEmail::Component::HeadStyle.build(doc)
84
- BootstrapEmail::Component::VersionComment.build(doc)
87
+ BootstrapEmail::Converter::HeadStyle.build(doc)
88
+ BootstrapEmail::Converter::VersionComment.build(doc)
85
89
  end
86
90
 
87
91
  def finalize_document!
88
- html = BootstrapEmail::Component::ForceEncoding.replace(doc.to_html)
92
+ html = doc.to_html(encoding: 'US-ASCII')
93
+ html = BootstrapEmail::Converter::ForceEncoding.replace(html)
89
94
  case type
90
95
  when :rails
91
96
  (@mail.html_part || @mail).body = html
@@ -0,0 +1,50 @@
1
+ module BootstrapEmail
2
+ class Config
3
+ attr_writer :sass_email_location # path to main sass file
4
+ attr_writer :sass_head_location # path to head sass file
5
+ attr_writer :sass_load_paths # array of directories for loading sass imports
6
+ attr_writer :sass_cache_location # path to tmp folder for sass cache
7
+ attr_writer :sass_log_enabled # turn on or off sass log when caching new sass
8
+
9
+ def load_options(options)
10
+ file = File.expand_path('bootstrap-email.config.rb', Dir.pwd)
11
+ if options[:config_path]
12
+ require_relative options[:config_path]
13
+ elsif File.exist?(file)
14
+ require_relative file
15
+ end
16
+ options.each { |name, value| instance_variable_set("@#{name}", value) }
17
+ end
18
+
19
+ def sass_location_for(type:)
20
+ ivar = instance_variable_get("@sass_#{type.sub('bootstrap-', '')}_location")
21
+ return ivar if ivar
22
+
23
+ lookup_locations = ["#{type}.scss", "app/assets/stylesheets/#{type}.scss"]
24
+ locations = lookup_locations.map { |location| File.expand_path(location, Dir.pwd) }.select { |location| File.exist?(location) }
25
+ locations.first if locations.any?
26
+ end
27
+
28
+ def sass_load_paths
29
+ paths_array = [SassCache::SASS_DIR]
30
+ @sass_load_paths ||= []
31
+ paths_array.concat(@sass_load_paths)
32
+ end
33
+
34
+ def sass_cache_location
35
+ @sass_cache_location ||= begin
36
+ if defined?(::Rails) && ::Rails.root
37
+ ::Rails.root.join('tmp', 'cache', 'bootstrap-email', '.sass-cache')
38
+ elsif File.writable?(Dir.pwd)
39
+ File.join(Dir.pwd, '.sass-cache', 'bootstrap-email')
40
+ else
41
+ File.join(Dir.tmpdir, '.sass-cache', 'bootstrap-email')
42
+ end
43
+ end
44
+ end
45
+
46
+ def sass_log_enabled?
47
+ defined?(@sass_log_enabled) ? @sass_log_enabled : true
48
+ end
49
+ end
50
+ end
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Alert < Base
4
4
  def build
5
5
  each_node('.alert') do |node|
@@ -1,9 +1,9 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Align < Base
4
4
  def build
5
5
  ['left', 'center', 'right'].each do |type|
6
- full_type = "align-#{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
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Badge < Base
4
4
  def build
5
5
  each_node('.badge') do |node|
@@ -1,9 +1,10 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Base
4
4
  attr_reader :doc
5
5
  def initialize(doc)
6
6
  @doc = doc
7
+ @cached_templates = {}
7
8
  end
8
9
 
9
10
  def self.build(doc)
@@ -13,11 +14,19 @@ module BootstrapEmail
13
14
  private
14
15
 
15
16
  def template(file, locals_hash = {})
16
- locals_hash[:classes] = locals_hash[:classes].split.join(' ') if locals_hash[:classes]
17
- BootstrapEmail::Erb.template(
18
- File.expand_path("../../../core/templates/#{file}.html.erb", __dir__),
19
- locals_hash
20
- )
17
+ locals_hash[:classes] = locals_hash[:classes].to_s.split.join(' ')
18
+ locals_hash[:content] ||= nil
19
+ if @cached_templates[file]
20
+ string = @cached_templates[file]
21
+ else
22
+ path = File.expand_path("../../../core/templates/#{file}.html", __dir__)
23
+ string = File.read(path).chop # read and remove trailing newline
24
+ @cached_templates[file] = string
25
+ end
26
+ locals_hash.each do |key, value|
27
+ string = string.sub("{{ #{key} }}", value.to_s)
28
+ end
29
+ string
21
30
  end
22
31
 
23
32
  def each_node(css_lookup, &blk)
@@ -27,7 +36,7 @@ module BootstrapEmail
27
36
 
28
37
  def add_class(node, class_name)
29
38
  node['class'] ||= ''
30
- node['class'] += class_name
39
+ node['class'] += node['class'].length.zero? ? class_name : " #{class_name}"
31
40
  end
32
41
 
33
42
  def margin?(node)
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Block < Base
4
4
  def build
5
5
  each_node('block, .to-table') do |node|
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Body < Base
4
4
  def build
5
5
  body = doc.at_css('body')
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Button < Base
4
4
  def build
5
5
  each_node('.btn') do |node|
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Card < Base
4
4
  def build
5
5
  each_node('.card') do |node|
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Color < Base
4
4
  def build
5
5
  each_node('*[class*=bg-]') do |node|
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Container < Base
4
4
  def build
5
5
  each_node('.container') do |node|
@@ -0,0 +1,14 @@
1
+ module BootstrapEmail
2
+ module Converter
3
+ class ForceEncoding < Base
4
+ def self.replace(html)
5
+ # force utf-8 character encoded in iOS Mail: https://github.com/bootstrap-email/bootstrap-email/issues/50
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
+ )
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,9 +1,9 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Grid < Base
4
4
  def build
5
5
  each_node('.row') do |node|
6
- node.replace(template('table-to-tr', classes: node['class'], contents: node.inner_html))
6
+ node.replace(template('div', classes: node['class'], contents: template('table-to-tr', contents: node.inner_html)))
7
7
  end
8
8
  each_node('*[class*=col]') do |node|
9
9
  node.replace(template('td', classes: node['class'], contents: node.inner_html))
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class HeadStyle < Base
4
4
  def build
5
5
  doc.at_css('head').add_child(bootstrap_email_head)
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Hr < Base
4
4
  def build
5
5
  each_node('hr') do |node|
@@ -1,11 +1,11 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Margin < Base
4
4
  def build
5
- each_node('*[class*=my-], *[class*=mt-], *[class*=mb-]') do |node|
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)
@@ -0,0 +1,16 @@
1
+ module BootstrapEmail
2
+ module Converter
3
+ class Padding < Base
4
+ def build
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
+ next if ['table', 'td', 'a'].include?(node.name)
7
+
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
+ node.replace(template('table', classes: classes, contents: node.to_html))
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Paragraph < Base
4
4
  def build
5
5
  each_node('p') do |node|
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class PreviewText < Base
4
4
  def build
5
5
  preview_node = doc.at_css('preview')
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Spacer < Base
4
4
  def build
5
5
  each_node('*[class*=s-]') do |node|
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Spacing < Base
4
4
  def build
5
5
  each_node('*[class*=space-y-]') do |node|
@@ -1,13 +1,13 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Stack < Base
4
4
  def build
5
- stack_x
6
- stack_y
5
+ stack_row
6
+ stack_col
7
7
  end
8
8
 
9
- def stack_x
10
- each_node('.stack-x') do |node|
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 stack_y
20
- each_node('.stack-y') do |node|
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)
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class Table < Base
4
4
  def build
5
5
  each_node('table') do |node|
@@ -1,5 +1,5 @@
1
1
  module BootstrapEmail
2
- module Component
2
+ module Converter
3
3
  class VersionComment < Base
4
4
  def build
5
5
  doc.at_css('head').prepend_child(bootstrap_email_comment)
@@ -1,24 +1,27 @@
1
1
  module BootstrapEmail
2
2
  class SassCache
3
- CACHE_DIR = File.expand_path('../../.sass-cache', __dir__)
4
3
  SASS_DIR = File.expand_path('../../core', __dir__)
5
4
 
6
- def self.compile(type, config_path: nil, style: :compressed)
7
- new(type, config_path, style).compile
5
+ def self.compile(type, style: :compressed)
6
+ new(type, style).compile
8
7
  end
9
8
 
10
9
  attr_accessor :type, :style, :file_path, :config_file, :checksum
11
10
 
12
- def initialize(type, config_path, style)
11
+ def initialize(type, style)
13
12
  self.type = type
14
13
  self.style = style
15
14
  self.file_path = "#{SASS_DIR}/#{type}"
16
- self.config_file = load_config(config_path)
15
+ self.config_file = load_config
17
16
  self.checksum = checksum_files
18
17
  end
19
18
 
19
+ def cache_dir
20
+ BootstrapEmail.config.sass_cache_location
21
+ end
22
+
20
23
  def compile
21
- cache_path = "#{CACHE_DIR}/#{checksum}/#{type}.css"
24
+ cache_path = "#{cache_dir}/#{checksum}/#{type}.css"
22
25
  unless cached?(cache_path)
23
26
  compile_and_cache_scss(cache_path)
24
27
  end
@@ -27,16 +30,9 @@ module BootstrapEmail
27
30
 
28
31
  private
29
32
 
30
- def load_config(config_path)
31
- lookup_locations = ["#{type}.config.scss", "app/assets/stylesheets/#{type}.config.scss"]
32
- locations = lookup_locations.select { |location| File.exist?(File.expand_path(location, Dir.pwd)) }
33
- if config_path && File.exist?(config_path)
34
- # check if custom config was passed in
35
- replace_config(File.read(config_path))
36
- elsif locations.any?
37
- # look for common lookup locations of config
38
- replace_config(File.read(File.expand_path(locations.first, Dir.pwd)))
39
- end
33
+ def load_config
34
+ path = BootstrapEmail.config.sass_location_for(type: type)
35
+ replace_config(File.read(path)) if path
40
36
  end
41
37
 
42
38
  def replace_config(config_file)
@@ -58,10 +54,11 @@ module BootstrapEmail
58
54
  def compile_and_cache_scss(cache_path)
59
55
  file = config_file || File.read("#{file_path}.scss")
60
56
  css = SassC::Engine.new(file, style: style).render
61
- Dir.mkdir(CACHE_DIR) unless File.directory?(CACHE_DIR)
62
- Dir.mkdir("#{CACHE_DIR}/#{checksum}") unless File.directory?("#{CACHE_DIR}/#{checksum}")
57
+ FileUtils.mkdir_p("#{cache_dir}/#{checksum}") unless File.directory?("#{cache_dir}/#{checksum}")
63
58
  File.write(cache_path, css)
64
- puts "New css file cached for #{type}"
59
+ if BootstrapEmail.config.sass_log_enabled?
60
+ puts "New css file cached for #{type}"
61
+ end
65
62
  end
66
63
  end
67
64
  end
@@ -0,0 +1,27 @@
1
+ module BootstrapEmail
2
+ class << self
3
+ def config
4
+ @config ||= BootstrapEmail::Config.new
5
+ @config
6
+ end
7
+
8
+ def load_options(options)
9
+ @config ||= BootstrapEmail::Config.new
10
+ @config.load_options(options)
11
+ @config
12
+ end
13
+
14
+ def configure(&proc)
15
+ @config ||= BootstrapEmail::Config.new
16
+ yield @config
17
+ end
18
+
19
+ def reset_config!
20
+ remove_instance_variable :@config if defined?(@config)
21
+ end
22
+
23
+ def clear_sass_cache!
24
+ FileUtils.rm_rf(BootstrapEmail.config.sass_cache_location)
25
+ end
26
+ end
27
+ end
@@ -5,6 +5,7 @@ require 'premailer'
5
5
  require 'sassc'
6
6
  require 'digest/sha1'
7
7
  require 'css_parser'
8
+ require 'fileutils'
8
9
 
9
10
  begin
10
11
  require 'rails'
@@ -14,13 +15,14 @@ if defined?(Rails)
14
15
  require 'action_mailer'
15
16
  end
16
17
 
17
- require_relative 'bootstrap-email/initialize'
18
+ require_relative 'bootstrap-email/config'
19
+ require_relative 'bootstrap-email/setup'
18
20
  require_relative 'bootstrap-email/erb'
19
21
  require_relative 'bootstrap-email/compiler'
20
22
  require_relative 'bootstrap-email/sass_cache'
21
23
  require_relative 'bootstrap-email/version'
22
- require_relative 'bootstrap-email/components/base'
23
- Dir[File.join(__dir__, 'bootstrap-email/components', '*.rb')].each { |file| require_relative file }
24
+ require_relative 'bootstrap-email/converters/base'
25
+ Dir[File.join(__dir__, 'bootstrap-email/converters', '*.rb')].each { |file| require_relative file }
24
26
 
25
27
  if defined?(Rails)
26
28
  require_relative 'bootstrap-email/rails/action_mailer'
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.0.alpha2.1
4
+ version: 1.0.0
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-03-17 00:00:00.000000000 Z
11
+ date: 2021-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -92,46 +92,47 @@ files:
92
92
  - core/scss/utilities/_text-decoration.scss
93
93
  - core/scss/utilities/_typography.scss
94
94
  - core/scss/utilities/_valign.scss
95
- - core/templates/body.html.erb
96
- - core/templates/container.html.erb
97
- - core/templates/div.html.erb
98
- - core/templates/table-left.html.erb
99
- - core/templates/table-to-tbody.html.erb
100
- - core/templates/table-to-tr.html.erb
101
- - core/templates/table.html.erb
102
- - core/templates/td.html.erb
103
- - core/templates/tr.html.erb
95
+ - core/templates/body.html
96
+ - core/templates/container.html
97
+ - core/templates/div.html
98
+ - core/templates/table-left.html
99
+ - core/templates/table-to-tbody.html
100
+ - core/templates/table-to-tr.html
101
+ - core/templates/table.html
102
+ - core/templates/td.html
103
+ - core/templates/tr.html
104
104
  - lib/bootstrap-email.rb
105
105
  - lib/bootstrap-email/bootstrap_email_cli.rb
106
106
  - lib/bootstrap-email/compiler.rb
107
- - lib/bootstrap-email/components/alert.rb
108
- - lib/bootstrap-email/components/align.rb
109
- - lib/bootstrap-email/components/badge.rb
110
- - lib/bootstrap-email/components/base.rb
111
- - lib/bootstrap-email/components/block.rb
112
- - lib/bootstrap-email/components/body.rb
113
- - lib/bootstrap-email/components/button.rb
114
- - lib/bootstrap-email/components/card.rb
115
- - lib/bootstrap-email/components/color.rb
116
- - lib/bootstrap-email/components/container.rb
117
- - lib/bootstrap-email/components/force_encoding.rb
118
- - lib/bootstrap-email/components/grid.rb
119
- - lib/bootstrap-email/components/head_style.rb
120
- - lib/bootstrap-email/components/hr.rb
121
- - lib/bootstrap-email/components/margin.rb
122
- - lib/bootstrap-email/components/padding.rb
123
- - lib/bootstrap-email/components/paragraph.rb
124
- - lib/bootstrap-email/components/preview_text.rb
125
- - lib/bootstrap-email/components/spacer.rb
126
- - lib/bootstrap-email/components/spacing.rb
127
- - lib/bootstrap-email/components/stack.rb
128
- - lib/bootstrap-email/components/table.rb
129
- - lib/bootstrap-email/components/version_comment.rb
107
+ - lib/bootstrap-email/config.rb
108
+ - lib/bootstrap-email/converters/alert.rb
109
+ - lib/bootstrap-email/converters/align.rb
110
+ - lib/bootstrap-email/converters/badge.rb
111
+ - lib/bootstrap-email/converters/base.rb
112
+ - lib/bootstrap-email/converters/block.rb
113
+ - lib/bootstrap-email/converters/body.rb
114
+ - lib/bootstrap-email/converters/button.rb
115
+ - lib/bootstrap-email/converters/card.rb
116
+ - lib/bootstrap-email/converters/color.rb
117
+ - lib/bootstrap-email/converters/container.rb
118
+ - lib/bootstrap-email/converters/force_encoding.rb
119
+ - lib/bootstrap-email/converters/grid.rb
120
+ - lib/bootstrap-email/converters/head_style.rb
121
+ - lib/bootstrap-email/converters/hr.rb
122
+ - lib/bootstrap-email/converters/margin.rb
123
+ - lib/bootstrap-email/converters/padding.rb
124
+ - lib/bootstrap-email/converters/paragraph.rb
125
+ - lib/bootstrap-email/converters/preview_text.rb
126
+ - lib/bootstrap-email/converters/spacer.rb
127
+ - lib/bootstrap-email/converters/spacing.rb
128
+ - lib/bootstrap-email/converters/stack.rb
129
+ - lib/bootstrap-email/converters/table.rb
130
+ - lib/bootstrap-email/converters/version_comment.rb
130
131
  - lib/bootstrap-email/erb.rb
131
- - lib/bootstrap-email/initialize.rb
132
132
  - lib/bootstrap-email/rails/action_mailer.rb
133
133
  - lib/bootstrap-email/rails/engine.rb
134
134
  - lib/bootstrap-email/sass_cache.rb
135
+ - lib/bootstrap-email/setup.rb
135
136
  - lib/bootstrap-email/version.rb
136
137
  homepage: https://bootstrapemail.com
137
138
  licenses:
@@ -148,9 +149,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
148
149
  version: '2.0'
149
150
  required_rubygems_version: !ruby/object:Gem::Requirement
150
151
  requirements:
151
- - - ">"
152
+ - - ">="
152
153
  - !ruby/object:Gem::Version
153
- version: 1.3.1
154
+ version: '0'
154
155
  requirements: []
155
156
  rubygems_version: 3.0.3
156
157
  signing_key:
@@ -1,9 +0,0 @@
1
- <table class="<%= classes %>" valign="top" role="presentation">
2
- <tbody>
3
- <tr>
4
- <td valign="top">
5
- <%= contents %>
6
- </td>
7
- </tr>
8
- </tbody>
9
- </table>
@@ -1,3 +0,0 @@
1
- <div class="<%= classes %>">
2
- <%= contents %>
3
- </div>
@@ -1,9 +0,0 @@
1
- <table class="<%= classes %>" align="left" role="presentation">
2
- <tbody>
3
- <tr>
4
- <td>
5
- <%= contents %>
6
- </td>
7
- </tr>
8
- </tbody>
9
- </table>
@@ -1,5 +0,0 @@
1
- <table class="<%= classes %>" role="presentation">
2
- <tbody>
3
- <%= contents %>
4
- </tbody>
5
- </table>
@@ -1,7 +0,0 @@
1
- <table class="<%= classes %>" role="presentation">
2
- <tbody>
3
- <tr>
4
- <%= contents %>
5
- </tr>
6
- </tbody>
7
- </table>
@@ -1,9 +0,0 @@
1
- <table class="<%= classes %>" role="presentation">
2
- <tbody>
3
- <tr>
4
- <td>
5
- <%= contents %>
6
- </td>
7
- </tr>
8
- </tbody>
9
- </table>
@@ -1,3 +0,0 @@
1
- <td class="<%= classes %>">
2
- <%= contents %>
3
- </td>
@@ -1,16 +0,0 @@
1
- module BootstrapEmail
2
- module Component
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
- def self.replace(html)
10
- # 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('<force-encoding></force-encoding>', '<div id="force-encoding-to-utf-8" style="display: none;">&#10175;</div>')
13
- end
14
- end
15
- end
16
- end
@@ -1,16 +0,0 @@
1
- module BootstrapEmail
2
- module Component
3
- class Padding < Base
4
- def build
5
- each_node('*[class*=p-], *[class*=pt-], *[class*=pr-], *[class*=pb-], *[class*=pl-], *[class*=px-], *[class*=py-]') do |node|
6
- next if ['table', 'td', 'a'].include?(node.name)
7
-
8
- padding_regex = /(p[trblxy]?-\d+)/
9
- classes = node['class'].scan(padding_regex).join(' ')
10
- node['class'] = node['class'].gsub(padding_regex, '')
11
- node.replace(template('table', classes: classes, contents: node.to_html))
12
- end
13
- end
14
- end
15
- end
16
- end
@@ -1 +0,0 @@
1
- Premailer::Adapter.use = :nokogiri_fast