premailer 1.27.0 → 1.28.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31108244f6afc74508eef1337a9b99adc7f2643b5412e2aacf808ecb8c520101
4
- data.tar.gz: b2f10188d4b7143050eb86e04776c38fc220ebb834da7871e838fe47db5fe9c5
3
+ metadata.gz: 7e9ea60eb04b53f20269417902391f03464d1dd263f98cb0884b65e1d019a9e5
4
+ data.tar.gz: 448daeae92d362f8ec092300793d729bed26622590f98122c27e379ab24b631f
5
5
  SHA512:
6
- metadata.gz: 4cd3655f0aa411da6d874dd50e2e1ab1c6f1cae4f9882cfa84a6ec2022174f5d9670d439527bb27618774f7f731f7ac24b35420c58926db159b4f81e85cb660d
7
- data.tar.gz: aa583335ee3a7b0de99320aff3c162d233825c99fbfe287ae13f12790c4b54728b7b0460861f928efe9ddae07416aafb229058f698267214e8b740ff94ea20a8
6
+ metadata.gz: 57c3c0f79e925c133c999c683e683bc1c7a3b0889baaa184b0bc39d41c869d677e269eb371b3231c20607bb267ff5797ea7b323a80d57db3d62266cd964e603b
7
+ data.tar.gz: fb2bb6a1f120102a6f6f4e54543fb315257f69bf8f1564dc3ba10d7fcbcc29bf8ff8247e38fd7bd3abbb6beeb38e899dc5e0015e858c371e1742c292cd3b8b92
data/README.md CHANGED
@@ -127,6 +127,75 @@ Premailer.new(
127
127
 
128
128
  [available options](https://premailer.github.io/premailer/Premailer.html#initialize-instance_method)
129
129
 
130
+ ## Support for CSS variables
131
+
132
+ The gem does not automatically replace CSS variables with their static values.
133
+
134
+ For example, if a variable is used to set the `font-weight` of an `h1` element, the result will be
135
+ ```html
136
+ <h1 style="
137
+ font-size:3rem;
138
+ font-weight:var(--bulma-content-heading-weight);">
139
+ Title</h1>
140
+ ```
141
+
142
+ This causes the `font-weight` value to be the CSS variable call `var(--bulma-content-heading-weight);` instead of its static value.
143
+
144
+ ### Replace CSS variable calls with their static values
145
+
146
+ The following section instructs how to replace CSS variables with their static value in the context of a Ruby on Rails application.
147
+
148
+ Install the `postcss-css-variables` plugin for PostCSS to process the CSS variables.
149
+
150
+ ```shell
151
+ yarn add postcss postcss-cli postcss-css-variables
152
+ ```
153
+
154
+ To configure the plugin, create the file `postcss.config.js` in the root directory with the content:
155
+
156
+ ```javascript
157
+ module.exports = {
158
+ plugins: [
159
+ // https://github.com/MadLittleMods/postcss-css-variables to transform the css
160
+ require("postcss-css-variables")({
161
+ preserve: false, // Set to false to replace variables with static values
162
+ }),
163
+ ],
164
+ };
165
+ ```
166
+
167
+ In the `package.json` file, add the new "build:emails" to the scripts.<br>Replace `./app/assets/stylesheets/emails.css` with your file path:
168
+ ```json
169
+ "scripts": {
170
+ "build:emails": "postcss ./app/assets/stylesheets/emails.css -o ./app/assets/builds/emails.css"
171
+ }
172
+ ```
173
+
174
+ The previous script processes and overwrites the file at `./app/assets/stylesheets/emails.css` with PostCSS using its `postcss-css-variables` plugin, replacing the CSS variables with their static value.
175
+
176
+ If the file to be processed is not `.css`, but `.scss`, it needs to be converted first to `.css`, then have its variables replaced. The script would then be
177
+
178
+ ```json
179
+ "scripts": {
180
+ "build:emails": "sass ./app/assets/stylesheets/emails.scss:./app/assets/builds/emails.css --no-source-map --load-path=node_modules && postcss ./app/assets/builds/emails.css -o ./app/assets/builds/emails.css"
181
+ }
182
+ ```
183
+
184
+ Next, to execute the script when running `bin/dev`, add the following line in the file `Procfile.dev`
185
+
186
+ ```
187
+ emails_css: yarn build:emails --watch
188
+ ```
189
+
190
+ The srcipt can also be executed separately with the command
191
+
192
+ ```shell
193
+ yarn build:emails
194
+ ```
195
+
196
+ ### Caveat
197
+
198
+ The variables must be declared before use. Otherwise, their values when called will be set to `undefined`.
130
199
 
131
200
  ## Contributions
132
201
 
@@ -23,19 +23,19 @@ class Premailer
23
23
  # Iterate through the rules and merge them into the HTML
24
24
  @css_parser.each_selector(:all) do |selector, declaration, specificity, media_types|
25
25
  # Save un-mergable rules separately
26
- selector.gsub!(/:link([\s]*)+/i) { |m| $1 }
26
+ selector.gsub!(/:link([\s]*)+/i) { |_m| $1 }
27
27
 
28
28
  # Convert element names to lower case
29
- selector.gsub!(/([\s]|^)([\w]+)/) { |m| $1.to_s + $2.to_s.downcase }
29
+ selector.gsub!(/([\s]|^)([\w]+)/) { |_m| $1.to_s + $2.to_s.downcase }
30
30
 
31
- if Premailer.is_media_query?(media_types) || selector =~ Premailer::RE_UNMERGABLE_SELECTORS
31
+ if Premailer.media_query?(media_types) || selector =~ Premailer::RE_UNMERGABLE_SELECTORS
32
32
  @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selectors: selector, block: declaration), media_types) unless @options[:preserve_styles]
33
33
  else
34
34
  begin
35
- if Premailer::RE_RESET_SELECTORS.match?(selector)
35
+ if Premailer::RE_RESET_SELECTORS.match?(selector) && !!@options[:preserve_reset]
36
36
  # this is in place to preserve the MailChimp CSS reset: http://github.com/mailchimp/Email-Blueprints/
37
37
  # however, this doesn't mean for testing pur
38
- @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selectors: selector, block: declaration)) unless !@options[:preserve_reset]
38
+ @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selectors: selector, block: declaration))
39
39
  end
40
40
 
41
41
  # Change single ID CSS selectors into xpath so that we can match more
@@ -43,14 +43,14 @@ class Premailer
43
43
  selector.gsub!(/\A\#([\w_\-]+)\Z/, '*[@id=\1]')
44
44
 
45
45
  doc.search(selector).each do |el|
46
- if el.elem? and (el.name != 'head' and el.parent.name != 'head')
46
+ if el.elem? && ((el.name != 'head') && (el.parent.name != 'head'))
47
47
  # Add a style attribute or append to the existing one
48
48
  block = "[SPEC=#{specificity}[#{declaration}]]"
49
49
  el['style'] = (el.attributes['style'].to_s ||= '') + ' ' + block
50
50
  end
51
51
  end
52
52
  rescue ::Nokogiri::SyntaxError, RuntimeError, ArgumentError
53
- $stderr.puts "CSS syntax error with selector: #{selector}" if @options[:verbose]
53
+ warn "CSS syntax error with selector: #{selector}" if @options[:verbose]
54
54
  next
55
55
  end
56
56
  end
@@ -63,7 +63,7 @@ class Premailer
63
63
  doc.search("*[@style]").each do |el|
64
64
  style = el.attributes['style'].to_s
65
65
 
66
- declarations = style.scan(/\[SPEC\=([\d]+)\[(.[^\]\]]*)\]\]/m).filter_map do |declaration|
66
+ declarations = style.scan(/\[SPEC=([\d]+)\[(.[^\]]*)\]\]/m).filter_map do |declaration|
67
67
  rs = Premailer::CachedRuleSet.new(block: declaration[1].to_s, specificity: declaration[0].to_i)
68
68
  rs.expand_shorthand!
69
69
  rs
@@ -80,9 +80,9 @@ class Premailer
80
80
  end
81
81
 
82
82
  # Duplicate CSS attributes as HTML attributes
83
- if Premailer::RELATED_ATTRIBUTES.has_key?(el.name) && @options[:css_to_attributes]
83
+ if Premailer::RELATED_ATTRIBUTES.key?(el.name) && @options[:css_to_attributes]
84
84
  Premailer::RELATED_ATTRIBUTES[el.name].each do |css_attr, html_attr|
85
- if el[html_attr].nil? and not merged[css_attr].empty?
85
+ if el[html_attr].nil? && !merged[css_attr].empty?
86
86
  new_val = merged[css_attr].dup
87
87
 
88
88
  # Remove url() function wrapper
@@ -117,9 +117,9 @@ class Premailer
117
117
 
118
118
  doc = write_unmergable_css_rules(doc, @unmergable_rules) unless @options[:drop_unmergeable_css_rules]
119
119
 
120
- if @options[:remove_classes] or @options[:remove_comments]
120
+ if @options[:remove_classes] || @options[:remove_comments]
121
121
  doc.traverse do |el|
122
- if el.comment? and @options[:remove_comments]
122
+ if el.comment? && @options[:remove_comments]
123
123
  el.remove
124
124
  elsif el.element?
125
125
  el.remove_attribute('class') if @options[:remove_classes]
@@ -131,7 +131,7 @@ class Premailer
131
131
  # find all anchor's targets and hash them
132
132
  targets = []
133
133
  doc.search("a[@href^='#']").each do |el|
134
- target = el.get_attribute('href')[1..-1]
134
+ target = el.get_attribute('href')[1..]
135
135
  targets << target
136
136
  el.set_attribute('href', "#" + Digest::SHA256.hexdigest(target))
137
137
  end
@@ -153,7 +153,7 @@ class Premailer
153
153
  end
154
154
 
155
155
  @processed_doc = doc
156
- if is_xhtml?
156
+ if xhtml?
157
157
  # we don't want to encode carriage returns
158
158
  @processed_doc.to_xhtml(:encoding => @options[:output_encoding]).gsub(/&\#(xD|13);/i, "\r")
159
159
  else
@@ -175,17 +175,16 @@ class Premailer
175
175
  style_tag.content = styles
176
176
  doc.add_child(style_tag)
177
177
  else
178
- style_tag = doc.create_element "style", "#{styles}"
178
+ style_tag = doc.create_element "style", styles.to_s
179
179
  head = doc.at_css('head')
180
- head ||= doc.root.first_element_child.add_previous_sibling(doc.create_element "head") if doc.root && doc.root.first_element_child
181
- head ||= doc.add_child(doc.create_element "head")
180
+ head ||= doc.root.first_element_child.add_previous_sibling(doc.create_element("head")) if doc.root&.first_element_child
181
+ head ||= doc.add_child(doc.create_element("head"))
182
182
  head << style_tag
183
183
  end
184
184
  end
185
185
  doc
186
186
  end
187
187
 
188
-
189
188
  # Converts the HTML document to a format suitable for plain-text e-mail.
190
189
  #
191
190
  # If present, uses the <body> element as its base; otherwise uses the whole document.
@@ -195,17 +194,17 @@ class Premailer
195
194
  html_src = ''
196
195
  begin
197
196
  html_src = @doc.at("body").inner_html
198
- rescue;
197
+ rescue StandardError
199
198
  end
200
199
 
201
- html_src = @doc.to_html unless html_src and not html_src.empty?
200
+ html_src = @doc.to_html unless html_src && !html_src.empty?
202
201
  convert_to_text(html_src, @options[:line_length], @html_encoding)
203
202
  end
204
203
 
205
204
  # Gets the original HTML as a string.
206
205
  # @return [String] HTML.
207
206
  def to_s
208
- if is_xhtml?
207
+ if xhtml?
209
208
  @doc.to_xhtml(:encoding => nil)
210
209
  else
211
210
  @doc.to_html(:encoding => nil)
@@ -219,13 +218,13 @@ class Premailer
219
218
  thing = nil
220
219
 
221
220
  # TODO: duplicate options
222
- if @options[:with_html_string] or @options[:inline] or input.respond_to?(:read)
221
+ if @options[:with_html_string] || @options[:inline] || input.respond_to?(:read)
223
222
  thing = input
224
223
  elsif @is_local_file
225
224
  @base_dir = File.dirname(input)
226
225
  thing = File.open(input, 'r')
227
226
  else
228
- thing = URI.open(input)
227
+ thing = URI.parse(input).open
229
228
  end
230
229
 
231
230
  if thing.respond_to?(:read)
@@ -236,7 +235,7 @@ class Premailer
236
235
  doc = nil
237
236
 
238
237
  # Handle HTML entities
239
- if @options[:replace_html_entities] == true and thing.is_a?(String)
238
+ if (@options[:replace_html_entities] == true) && thing.is_a?(String)
240
239
  thing = +thing
241
240
  HTML_ENTITIES.map do |entity, replacement|
242
241
  thing.gsub! entity, replacement
@@ -246,7 +245,7 @@ class Premailer
246
245
  doc = if @options[:html_fragment]
247
246
  ::Nokogiri::HTML.fragment(thing, encoding)
248
247
  else
249
- ::Nokogiri::HTML(thing, nil, encoding) { |c| c.recover }
248
+ ::Nokogiri::HTML(thing, nil, encoding, &:recover)
250
249
  end
251
250
 
252
251
  # Fix for removing any CDATA tags from both style and script tags inserted per
@@ -254,13 +253,12 @@ class Premailer
254
253
  # https://github.com/premailer/premailer/issues/199
255
254
  ['style', 'script'].each do |tag|
256
255
  doc.search(tag).children.each do |child|
257
- child.swap(child.text()) if child.cdata?
256
+ child.swap(child.text) if child.cdata?
258
257
  end
259
258
  end
260
259
 
261
260
  doc
262
261
  end
263
-
264
262
  end
265
263
  end
266
264
  end
@@ -27,34 +27,33 @@ class Premailer
27
27
 
28
28
  # Iterate through the rules and merge them into the HTML
29
29
  @css_parser.each_selector(:all) do |selector, declaration, specificity, media_types|
30
-
31
30
  # Save un-mergable rules separately
32
- selector.gsub!(/:link([\s]*)+/i) { |m| $1 }
31
+ selector.gsub!(/:link([\s]*)+/i) { |_m| $1 }
33
32
 
34
33
  # Convert element names to lower case
35
- selector.gsub!(/([\s]|^)([\w]+)/) { |m| $1.to_s + $2.to_s.downcase }
34
+ selector.gsub!(/([\s]|^)([\w]+)/) { |_m| $1.to_s + $2.to_s.downcase }
36
35
 
37
- if Premailer.is_media_query?(media_types) || selector =~ Premailer::RE_UNMERGABLE_SELECTORS
36
+ if Premailer.media_query?(media_types) || selector =~ Premailer::RE_UNMERGABLE_SELECTORS
38
37
  @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selectors: selector, block: declaration), media_types) unless @options[:preserve_styles]
39
38
  else
40
39
  begin
41
- if Premailer::RE_RESET_SELECTORS.match?(selector)
40
+ if Premailer::RE_RESET_SELECTORS.match?(selector) && !!@options[:preserve_reset]
42
41
  # this is in place to preserve the MailChimp CSS reset: http://github.com/mailchimp/Email-Blueprints/
43
42
  # however, this doesn't mean for testing pur
44
- @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selectors: selector, block: declaration)) unless !@options[:preserve_reset]
43
+ @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selectors: selector, block: declaration))
45
44
  end
46
45
 
47
46
  # Try the new index based technique. If not supported, fall back to the old brute force one.
48
47
  nodes = match_selector(index, all_nodes, descendants, selector) || doc.search(selector)
49
48
  nodes.each do |el|
50
- if el.elem? and (el.name != 'head' and el.parent.name != 'head')
49
+ if el.elem? && ((el.name != 'head') && (el.parent.name != 'head'))
51
50
  # Add a style attribute or append to the existing one
52
51
  block = "[SPEC=#{specificity}[#{declaration}]]"
53
52
  el['style'] = (el.attributes['style'].to_s ||= '') + ' ' + block
54
53
  end
55
54
  end
56
55
  rescue ::Nokogiri::SyntaxError, RuntimeError, ArgumentError
57
- $stderr.puts "CSS syntax error with selector: #{selector}" if @options[:verbose]
56
+ warn "CSS syntax error with selector: #{selector}" if @options[:verbose]
58
57
  next
59
58
  end
60
59
  end
@@ -68,13 +67,11 @@ class Premailer
68
67
  style = el.attributes['style'].to_s
69
68
 
70
69
  declarations = []
71
- style.scan(/\[SPEC\=([\d]+)\[(.[^\]\]]*)\]\]/m).each do |declaration|
72
- begin
73
- rs = CssParser::RuleSet.new(block: declaration[1].to_s, specificity: declaration[0].to_i)
74
- declarations << rs
75
- rescue ArgumentError => e
76
- raise e if @options[:rule_set_exceptions]
77
- end
70
+ style.scan(/\[SPEC=([\d]+)\[(.[^\]]*)\]\]/m).each do |declaration|
71
+ rs = CssParser::RuleSet.new(block: declaration[1].to_s, specificity: declaration[0].to_i)
72
+ declarations << rs
73
+ rescue ArgumentError => e
74
+ raise e if @options[:rule_set_exceptions]
78
75
  end
79
76
 
80
77
  # Perform style folding
@@ -86,9 +83,9 @@ class Premailer
86
83
  end
87
84
 
88
85
  # Duplicate CSS attributes as HTML attributes
89
- if Premailer::RELATED_ATTRIBUTES.has_key?(el.name) && @options[:css_to_attributes]
86
+ if Premailer::RELATED_ATTRIBUTES.key?(el.name) && @options[:css_to_attributes]
90
87
  Premailer::RELATED_ATTRIBUTES[el.name].each do |css_attr, html_attr|
91
- if el[html_attr].nil? and not merged[css_attr].empty?
88
+ if el[html_attr].nil? && !merged[css_attr].empty?
92
89
  new_val = merged[css_attr].dup
93
90
 
94
91
  # Remove url() function wrapper
@@ -123,9 +120,9 @@ class Premailer
123
120
 
124
121
  doc = write_unmergable_css_rules(doc, @unmergable_rules) unless @options[:drop_unmergeable_css_rules]
125
122
 
126
- if @options[:remove_classes] or @options[:remove_comments]
123
+ if @options[:remove_classes] || @options[:remove_comments]
127
124
  doc.traverse do |el|
128
- if el.comment? and @options[:remove_comments]
125
+ if el.comment? && @options[:remove_comments]
129
126
  el.remove
130
127
  elsif el.element?
131
128
  el.remove_attribute('class') if @options[:remove_classes]
@@ -137,7 +134,7 @@ class Premailer
137
134
  # find all anchor's targets and hash them
138
135
  targets = []
139
136
  doc.search("a[@href^='#']").each do |el|
140
- target = el.get_attribute('href')[1..-1]
137
+ target = el.get_attribute('href')[1..]
141
138
  targets << target
142
139
  el.set_attribute('href', "#" + Digest::SHA256.hexdigest(target))
143
140
  end
@@ -159,7 +156,7 @@ class Premailer
159
156
  end
160
157
 
161
158
  @processed_doc = doc
162
- if is_xhtml?
159
+ if xhtml?
163
160
  # we don't want to encode carriage returns
164
161
  @processed_doc.to_xhtml(:encoding => @options[:output_encoding]).gsub(/&\#(xD|13);/i, "\r")
165
162
  else
@@ -183,15 +180,14 @@ class Premailer
183
180
  else
184
181
  style_tag = doc.create_element "style", styles
185
182
  head = doc.at_css('head')
186
- head ||= doc.root.first_element_child.add_previous_sibling(doc.create_element "head") if doc.root && doc.root.first_element_child
187
- head ||= doc.add_child(doc.create_element "head")
183
+ head ||= doc.root.first_element_child.add_previous_sibling(doc.create_element("head")) if doc.root&.first_element_child
184
+ head ||= doc.add_child(doc.create_element("head"))
188
185
  head << style_tag
189
186
  end
190
187
  end
191
188
  doc
192
189
  end
193
190
 
194
-
195
191
  # Converts the HTML document to a format suitable for plain-text e-mail.
196
192
  #
197
193
  # If present, uses the <body> element as its base; otherwise uses the whole document.
@@ -201,17 +197,17 @@ class Premailer
201
197
  html_src = ''
202
198
  begin
203
199
  html_src = @doc.at("body").inner_html
204
- rescue;
200
+ rescue StandardError
205
201
  end
206
202
 
207
- html_src = @doc.to_html unless html_src and not html_src.empty?
203
+ html_src = @doc.to_html unless html_src && !html_src.empty?
208
204
  convert_to_text(html_src, @options[:line_length], @html_encoding)
209
205
  end
210
206
 
211
207
  # Gets the original HTML as a string.
212
208
  # @return [String] HTML.
213
209
  def to_s
214
- if is_xhtml?
210
+ if xhtml?
215
211
  @doc.to_xhtml(:encoding => nil)
216
212
  else
217
213
  @doc.to_html(:encoding => nil)
@@ -225,13 +221,13 @@ class Premailer
225
221
  thing = nil
226
222
 
227
223
  # TODO: duplicate options
228
- if @options[:with_html_string] or @options[:inline] or input.respond_to?(:read)
224
+ if @options[:with_html_string] || @options[:inline] || input.respond_to?(:read)
229
225
  thing = input
230
226
  elsif @is_local_file
231
227
  @base_dir = File.dirname(input)
232
228
  thing = File.open(input, 'r')
233
229
  else
234
- thing = URI.open(input)
230
+ thing = URI.parse(input).open
235
231
  end
236
232
 
237
233
  if thing.respond_to?(:read)
@@ -242,7 +238,7 @@ class Premailer
242
238
  doc = nil
243
239
 
244
240
  # Handle HTML entities
245
- if @options[:replace_html_entities] == true and thing.is_a?(String)
241
+ if (@options[:replace_html_entities] == true) && thing.is_a?(String)
246
242
  HTML_ENTITIES.map do |entity, replacement|
247
243
  thing.gsub! entity, replacement
248
244
  end
@@ -251,7 +247,7 @@ class Premailer
251
247
  doc = if @options[:html_fragment]
252
248
  ::Nokogiri::HTML.fragment(thing, encoding)
253
249
  else
254
- ::Nokogiri::HTML(thing, nil, encoding) { |c| c.recover }
250
+ ::Nokogiri::HTML(thing, nil, encoding, &:recover)
255
251
  end
256
252
 
257
253
  # Fix for removing any CDATA tags from both style and script tags inserted per
@@ -259,7 +255,7 @@ class Premailer
259
255
  # https://github.com/premailer/premailer/issues/199
260
256
  ['style', 'script'].each do |tag|
261
257
  doc.search(tag).children.each do |child|
262
- child.swap(child.text()) if child.cdata?
258
+ child.swap(child.text) if child.cdata?
263
259
  end
264
260
  end
265
261
 
@@ -283,7 +279,7 @@ class Premailer
283
279
  page.traverse do |node|
284
280
  all_nodes.push(node)
285
281
 
286
- if node != page then
282
+ if node != page
287
283
  index_ancestry(page, node, node.parent, descendants)
288
284
  end
289
285
 
@@ -294,7 +290,7 @@ class Premailer
294
290
  # Index the node by all class attributes it possesses.
295
291
  # Classes are modestly selective. Usually more than tag names
296
292
  # but less selective than ids.
297
- if node.has_attribute?("class") then
293
+ if node.has_attribute?("class")
298
294
  node.get_attribute("class").split(/\s+/).each do |c|
299
295
  c = '.' + c
300
296
  index[c] = (index[c] || Set.new).add(node)
@@ -303,7 +299,7 @@ class Premailer
303
299
 
304
300
  # Index the node by its "id" attribute if it has one.
305
301
  # This is usually the most selective of the three.
306
- if node.has_attribute?("id") then
302
+ if node.has_attribute?("id")
307
303
  id = '#' + node.get_attribute("id")
308
304
  index[id] = (index[id] || Set.new).add(node)
309
305
  end
@@ -325,9 +321,9 @@ class Premailer
325
321
  # @param descendants The running hash map of node -> set of nodes that maps descendants of a node.
326
322
  # @return The descendants argument after updating it.
327
323
  def index_ancestry(doc, elem, parent, descendants)
328
- if parent then
324
+ if parent
329
325
  descendants[parent] = (descendants[parent] || Set.new).add(elem)
330
- if doc != parent then
326
+ if doc != parent
331
327
  index_ancestry(doc, elem, parent.parent, descendants)
332
328
  end
333
329
  end
@@ -356,14 +352,14 @@ class Premailer
356
352
  # It will return nil when such a selector is passed, so you can take
357
353
  # action on the falsity of the return value.
358
354
  def match_selector(index, all_nodes, descendants, selector)
359
- if /[^-a-zA-Z0-9_\s.#]/.match?(selector) then
355
+ if /[^-a-zA-Z0-9_\s.#]/.match?(selector)
360
356
  return nil
361
357
  end
362
358
 
363
359
  take_children = false
364
360
  selector.split(/\s+/).reduce(all_nodes) do |base, spec|
365
361
  desc = base
366
- if take_children then
362
+ if take_children
367
363
  desc = Set.new
368
364
  base.each do |n|
369
365
  desc.merge(descendants[n])