premailer 1.23.0 → 1.27.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: ea6e9ef14eeb9cdffd7e718f976d9e71e50fb1f154c947c9ee9b97399f1aceeb
4
- data.tar.gz: 02d8f609acce2abb421f607e1937e35e4d36f12c609386bef808378f56e9753c
3
+ metadata.gz: 31108244f6afc74508eef1337a9b99adc7f2643b5412e2aacf808ecb8c520101
4
+ data.tar.gz: b2f10188d4b7143050eb86e04776c38fc220ebb834da7871e838fe47db5fe9c5
5
5
  SHA512:
6
- metadata.gz: d1e580add5528f240e2170bb2aed29171227d35ce8acc31d5c8ceed7ea3f211072f8db8257f9665bef5838c606c9f77a56a792482c3d5f730025a6448374a4bb
7
- data.tar.gz: 3afd5c1330b5b1ddff158e77260c0fc87876779e839f5f1beb641ea4c00d424db97c0b5410a566f08ac97a3615cd125c8d9198a77d5edf3ee5959abcc2058440
6
+ metadata.gz: 4cd3655f0aa411da6d874dd50e2e1ab1c6f1cae4f9882cfa84a6ec2022174f5d9670d439527bb27618774f7f731f7ac24b35420c58926db159b4f81e85cb660d
7
+ data.tar.gz: aa583335ee3a7b0de99320aff3c162d233825c99fbfe287ae13f12790c4b54728b7b0460861f928efe9ddae07416aafb229058f698267214e8b740ff94ea20a8
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  For the best HTML e-mail delivery results, CSS should be inline. This is a
6
6
  huge pain and a simple newsletter becomes un-managable very quickly. This
7
- script is my solution.
7
+ gem is a solution.
8
8
 
9
9
  * CSS styles are converted to inline style attributes
10
10
  - Checks `style` and `link[rel=stylesheet]` tags and preserves existing inline attributes
@@ -12,35 +12,26 @@ script is my solution.
12
12
  - Checks links in `href`, `src` and CSS `url('')`
13
13
  * CSS properties are checked against e-mail client capabilities
14
14
  - Based on the Email Standards Project's guides
15
- * A [plain text version](https://premailer.github.io/premailer/HtmlToPlainText.html) is created (optional)
15
+ * A [plain text version](#plain-text-version) is created (optional)
16
16
 
17
17
  ## Installation
18
18
 
19
- Install the Premailer gem from RubyGems.
20
-
21
19
  ```bash
22
20
  gem install premailer
23
21
  ```
24
22
 
25
- or add it to your `Gemfile` and run `bundle`.
26
-
27
23
  ## Example
28
24
 
29
25
  ```ruby
30
26
  require 'premailer'
31
27
 
32
- premailer = Premailer.new('http://example.com/myfile.html', :warn_level => Premailer::Warnings::SAFE)
28
+ premailer = Premailer.new('http://example.com/myfile.html', warn_level: Premailer::Warnings::SAFE)
33
29
 
34
- # Write the plain-text output
35
- # This must come before to_inline_css (https://github.com/premailer/premailer/issues/201)
36
- File.open("output.txt", "w") do |fout|
37
- fout.puts premailer.to_plain_text
38
- end
30
+ # Write the plain-text output (must come before to_inline_css)
31
+ File.write "output.txt", premailer.to_plain_text
39
32
 
40
33
  # Write the HTML output
41
- File.open("output.html", "w") do |fout|
42
- fout.puts premailer.to_inline_css
43
- end
34
+ File.write "output.html", premailer.to_inline_css
44
35
 
45
36
  # Output any CSS warnings
46
37
  premailer.warnings.each do |w|
@@ -50,17 +41,13 @@ end
50
41
 
51
42
  ## Adapters
52
43
 
53
- Premailer's default adapter is nokogiri if both nokogiri and nokogumbo are included in the Gemfile list. However, if you want to use a different adapter, you can choose to.
54
-
55
- There are three adapters in total (as of premailer 1.10.0)
56
-
57
44
  1. nokogiri (default)
58
- 2. nokogiri_fast
45
+ 2. nokogiri_fast (20x speed, more memory)
59
46
  3. nokogumbo
60
47
 
61
- hpricot adapter removed due to its EOL, please use `~>1.9.0` version if You still need it..
48
+ (hpricot adapter removed, use `~>1.9.0` version if you need it)
62
49
 
63
- `NokogiriFast` adapter improves the Algorithmic complexity of the running time by 20x with a slight compensation on memory. To switch to any of these adapters, add the following line. For example, if you want to include the `NokogiriFast` adapter,
50
+ Picking an adapter:
64
51
 
65
52
  ```ruby
66
53
  Premailer::Adapter.use = :nokogiri_fast
@@ -97,22 +84,56 @@ will result in
97
84
  <table cellspacing='5' width='500'>
98
85
  ```
99
86
 
100
- ## Configuration options
87
+ ## Plain text version
88
+
89
+ Premailer can generate a plain text version of your HTML. Links and images will be inlined.
101
90
 
102
- The behavior of Premailer can be configured by passing options in the initializer.
91
+ For example
103
92
 
104
- For example, the following will accept HTML from a string and will exclude unmergeable css from being added to the `<head>` of the output document.
93
+ ```html
94
+ <a href="https://example.com" >
95
+ <img src="https://github.com/premailer.png" alt="Premailer Logo" />
96
+ </a>
97
+ ```
105
98
 
99
+ will become
100
+
101
+ ```text
102
+ Premailer Logo ( https://example.com )
103
+ ```
104
+
105
+ To ignore/omit a section of HTML content from the plain text version, wrap it with the following comments.
106
+
107
+ ```html
108
+ <!-- start text/html -->
109
+ <p>This will be omitted from the plain text version.</p>
110
+ <p>
111
+ This is extremely helpful for <strong>removing email headers and footers</strong>
112
+ that aren't needed in the text version.
113
+ </p>
114
+ <!-- end text/html -->
115
+ ```
116
+
117
+ ## Configuration options
118
+
119
+ For example:
106
120
  ```ruby
107
- premailer = Premailer.new(html_string, with_html_string: true, drop_unmergeable_css_rules: true)
121
+ Premailer.new(
122
+ html, # html as string
123
+ with_html_string: true,
124
+ drop_unmergeable_css_rules: true
125
+ )
108
126
  ```
109
127
 
110
- [See here for a full list of the available options](https://premailer.github.io/premailer/Premailer.html#initialize-instance_method).
128
+ [available options](https://premailer.github.io/premailer/Premailer.html#initialize-instance_method)
111
129
 
112
130
 
113
131
  ## Contributions
114
132
 
115
- Contributions are most welcome. Premailer was rotting away in a private SVN repository for too long and could use some TLC. Fork and patch to your heart's content. Please don't increment the version numbers, though.
133
+ Contributions are most welcome.
134
+ Premailer was rotting away in a private SVN repository for too long and could use some TLC.
135
+ Fork and patch to your heart's content.
136
+ Please don't increment the version numbers.
116
137
 
117
138
  A few areas that are particularly in need of love:
118
139
 
@@ -129,4 +150,3 @@ and to [Campaign Monitor](https://www.campaignmonitor.com/) for supporting the w
129
150
  The source code can be found on [GitHub](https://github.com/premailer/premailer).
130
151
 
131
152
  Copyright by Alex Dunae (dunae.ca, e-mail 'code' at the same domain), 2007-2017. See [LICENSE.md](https://github.com/premailer/premailer/blob/master/LICENSE.md) for license details.
132
-
data/bin/premailer CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  # This binary used in rubygems environment only as part of installed gem
4
5
 
5
6
  require 'premailer/executor'
6
-
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  require 'nokogiri'
2
3
 
3
4
  class Premailer
4
5
  module Adapter
5
6
  # Nokogiri adapter
6
7
  module Nokogiri
8
+ WIDTH_AND_HIGHT = ['width', 'height'].freeze
7
9
 
8
10
  include AdapterHelper::RgbToHex
9
11
  # Merge CSS into the HTML document.
@@ -27,13 +29,13 @@ class Premailer
27
29
  selector.gsub!(/([\s]|^)([\w]+)/) { |m| $1.to_s + $2.to_s.downcase }
28
30
 
29
31
  if Premailer.is_media_query?(media_types) || selector =~ Premailer::RE_UNMERGABLE_SELECTORS
30
- @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selector, declaration), media_types) unless @options[:preserve_styles]
32
+ @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selectors: selector, block: declaration), media_types) unless @options[:preserve_styles]
31
33
  else
32
34
  begin
33
- if selector =~ Premailer::RE_RESET_SELECTORS
35
+ if Premailer::RE_RESET_SELECTORS.match?(selector)
34
36
  # this is in place to preserve the MailChimp CSS reset: http://github.com/mailchimp/Email-Blueprints/
35
37
  # however, this doesn't mean for testing pur
36
- @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selector, declaration)) unless !@options[:preserve_reset]
38
+ @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selectors: selector, block: declaration)) unless !@options[:preserve_reset]
37
39
  end
38
40
 
39
41
  # Change single ID CSS selectors into xpath so that we can match more
@@ -61,8 +63,8 @@ class Premailer
61
63
  doc.search("*[@style]").each do |el|
62
64
  style = el.attributes['style'].to_s
63
65
 
64
- declarations = style.scan(/\[SPEC\=([\d]+)\[(.[^\]\]]*)\]\]/).filter_map do |declaration|
65
- rs = Premailer::CachedRuleSet.new(nil, declaration[1].to_s, declaration[0].to_i)
66
+ declarations = style.scan(/\[SPEC\=([\d]+)\[(.[^\]\]]*)\]\]/m).filter_map do |declaration|
67
+ rs = Premailer::CachedRuleSet.new(block: declaration[1].to_s, specificity: declaration[0].to_i)
66
68
  rs.expand_shorthand!
67
69
  rs
68
70
  rescue ArgumentError => e
@@ -90,7 +92,7 @@ class Premailer
90
92
  new_val.gsub!(/;$|\s*!important/, '').strip!
91
93
 
92
94
  # For width and height tags, remove px units
93
- new_val.gsub!(/(\d+)px/, '\1') if %w[width height].include?(html_attr)
95
+ new_val.gsub!(/(\d+)px/, '\1') if WIDTH_AND_HIGHT.include?(html_attr)
94
96
 
95
97
  # For color-related tags, convert RGB to hex if specified by options
96
98
  new_val = ensure_hex(new_val) if css_attr.end_with?('color') && @options[:rgb_to_hex_attributes]
@@ -99,7 +101,7 @@ class Premailer
99
101
  end
100
102
 
101
103
  unless @options[:preserve_style_attribute]
102
- merged.instance_variable_get("@declarations").tap do |declarations|
104
+ merged.instance_variable_get(:@declarations).tap do |declarations|
103
105
  declarations.delete(css_attr)
104
106
  end
105
107
  end
@@ -235,6 +237,7 @@ class Premailer
235
237
 
236
238
  # Handle HTML entities
237
239
  if @options[:replace_html_entities] == true and thing.is_a?(String)
240
+ thing = +thing
238
241
  HTML_ENTITIES.map do |entity, replacement|
239
242
  thing.gsub! entity, replacement
240
243
  end
@@ -249,7 +252,7 @@ class Premailer
249
252
  # Fix for removing any CDATA tags from both style and script tags inserted per
250
253
  # https://github.com/sparklemotion/nokogiri/issues/311 and
251
254
  # https://github.com/premailer/premailer/issues/199
252
- %w(style script).each do |tag|
255
+ ['style', 'script'].each do |tag|
253
256
  doc.search(tag).children.each do |child|
254
257
  child.swap(child.text()) if child.cdata?
255
258
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  require 'nokogiri'
2
3
 
3
4
  class Premailer
4
5
  module Adapter
5
6
  # NokogiriFast adapter
6
7
  module NokogiriFast
8
+ WIDTH_AND_HEIGHT = ['width', 'height'].freeze
7
9
 
8
10
  include AdapterHelper::RgbToHex
9
11
  # Merge CSS into the HTML document.
@@ -33,13 +35,13 @@ class Premailer
33
35
  selector.gsub!(/([\s]|^)([\w]+)/) { |m| $1.to_s + $2.to_s.downcase }
34
36
 
35
37
  if Premailer.is_media_query?(media_types) || selector =~ Premailer::RE_UNMERGABLE_SELECTORS
36
- @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selector, declaration), media_types) unless @options[:preserve_styles]
38
+ @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selectors: selector, block: declaration), media_types) unless @options[:preserve_styles]
37
39
  else
38
40
  begin
39
- if selector =~ Premailer::RE_RESET_SELECTORS
41
+ if Premailer::RE_RESET_SELECTORS.match?(selector)
40
42
  # this is in place to preserve the MailChimp CSS reset: http://github.com/mailchimp/Email-Blueprints/
41
43
  # however, this doesn't mean for testing pur
42
- @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selector, declaration)) unless !@options[:preserve_reset]
44
+ @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selectors: selector, block: declaration)) unless !@options[:preserve_reset]
43
45
  end
44
46
 
45
47
  # Try the new index based technique. If not supported, fall back to the old brute force one.
@@ -66,9 +68,9 @@ class Premailer
66
68
  style = el.attributes['style'].to_s
67
69
 
68
70
  declarations = []
69
- style.scan(/\[SPEC\=([\d]+)\[(.[^\]\]]*)\]\]/).each do |declaration|
71
+ style.scan(/\[SPEC\=([\d]+)\[(.[^\]\]]*)\]\]/m).each do |declaration|
70
72
  begin
71
- rs = CssParser::RuleSet.new(nil, declaration[1].to_s, declaration[0].to_i)
73
+ rs = CssParser::RuleSet.new(block: declaration[1].to_s, specificity: declaration[0].to_i)
72
74
  declarations << rs
73
75
  rescue ArgumentError => e
74
76
  raise e if @options[:rule_set_exceptions]
@@ -96,7 +98,7 @@ class Premailer
96
98
  new_val.gsub!(/;$|\s*!important/, '').strip!
97
99
 
98
100
  # For width and height tags, remove px units
99
- new_val.gsub!(/(\d+)px/, '\1') if %w[width height].include?(html_attr)
101
+ new_val.gsub!(/(\d+)px/, '\1') if WIDTH_AND_HEIGHT.include?(html_attr)
100
102
 
101
103
  # For color-related tags, convert RGB to hex if specified by options
102
104
  new_val = ensure_hex(new_val) if css_attr.end_with?('color') && @options[:rgb_to_hex_attributes]
@@ -105,7 +107,7 @@ class Premailer
105
107
  end
106
108
 
107
109
  unless @options[:preserve_style_attribute]
108
- merged.instance_variable_get("@declarations").tap do |declarations|
110
+ merged.instance_variable_get(:@declarations).tap do |declarations|
109
111
  declarations.delete(css_attr)
110
112
  end
111
113
  end
@@ -255,7 +257,7 @@ class Premailer
255
257
  # Fix for removing any CDATA tags from both style and script tags inserted per
256
258
  # https://github.com/sparklemotion/nokogiri/issues/311 and
257
259
  # https://github.com/premailer/premailer/issues/199
258
- %w(style script).each do |tag|
260
+ ['style', 'script'].each do |tag|
259
261
  doc.search(tag).children.each do |child|
260
262
  child.swap(child.text()) if child.cdata?
261
263
  end
@@ -314,7 +316,7 @@ class Premailer
314
316
  index.default = Set.new
315
317
  descendants.default = Set.new
316
318
 
317
- return index, Set.new(all_nodes), descendants
319
+ [index, Set.new(all_nodes), descendants]
318
320
  end
319
321
 
320
322
  # @param doc The top level document
@@ -354,7 +356,7 @@ class Premailer
354
356
  # It will return nil when such a selector is passed, so you can take
355
357
  # action on the falsity of the return value.
356
358
  def match_selector(index, all_nodes, descendants, selector)
357
- if /[^-a-zA-Z0-9_\s.#]/.match(selector) then
359
+ if /[^-a-zA-Z0-9_\s.#]/.match?(selector) then
358
360
  return nil
359
361
  end
360
362
 
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
1
2
  class Premailer
2
3
  module Adapter
3
4
  # Nokogiri adapter
4
5
  module Nokogumbo
6
+ WIDTH_AND_HEIGHT = ['width', 'height'].freeze
5
7
 
6
8
  include AdapterHelper::RgbToHex
7
9
  # Merge CSS into the HTML document.
@@ -25,13 +27,13 @@ class Premailer
25
27
  selector.gsub!(/([\s]|^)([\w]+)/) { |m| $1.to_s + $2.to_s.downcase }
26
28
 
27
29
  if Premailer.is_media_query?(media_types) || selector =~ Premailer::RE_UNMERGABLE_SELECTORS
28
- @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selector, declaration), media_types) unless @options[:preserve_styles]
30
+ @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selectors: selector, block: declaration), media_types) unless @options[:preserve_styles]
29
31
  else
30
32
  begin
31
- if selector =~ Premailer::RE_RESET_SELECTORS
33
+ if Premailer::RE_RESET_SELECTORS.match?(selector)
32
34
  # this is in place to preserve the MailChimp CSS reset: http://github.com/mailchimp/Email-Blueprints/
33
35
  # however, this doesn't mean for testing pur
34
- @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selector, declaration)) unless !@options[:preserve_reset]
36
+ @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selectors: selector, block: declaration)) unless !@options[:preserve_reset]
35
37
  end
36
38
 
37
39
  # Change single ID CSS selectors into xpath so that we can match more
@@ -60,9 +62,9 @@ class Premailer
60
62
  style = el.attributes['style'].to_s
61
63
 
62
64
  declarations = []
63
- style.scan(/\[SPEC\=([\d]+)\[(.[^\]\]]*)\]\]/).each do |declaration|
65
+ style.scan(/\[SPEC\=([\d]+)\[(.[^\]\]]*)\]\]/m).each do |declaration|
64
66
  begin
65
- rs = CssParser::RuleSet.new(nil, declaration[1].to_s, declaration[0].to_i)
67
+ rs = CssParser::RuleSet.new(block: declaration[1].to_s, specificity: declaration[0].to_i)
66
68
  declarations << rs
67
69
  rescue ArgumentError => e
68
70
  raise e if @options[:rule_set_exceptions]
@@ -90,7 +92,7 @@ class Premailer
90
92
  new_val.gsub!(/;$|\s*!important/, '').strip!
91
93
 
92
94
  # For width and height tags, remove px units
93
- new_val.gsub!(/(\d+)px/, '\1') if %w[width height].include?(html_attr)
95
+ new_val.gsub!(/(\d+)px/, '\1') if WIDTH_AND_HEIGHT.include?(html_attr)
94
96
 
95
97
  # For color-related tags, convert RGB to hex if specified by options
96
98
  new_val = ensure_hex(new_val) if css_attr.end_with?('color') && @options[:rgb_to_hex_attributes]
@@ -99,7 +101,7 @@ class Premailer
99
101
  end
100
102
 
101
103
  unless @options[:preserve_style_attribute]
102
- merged.instance_variable_get("@declarations").tap do |declarations|
104
+ merged.instance_variable_get(:@declarations).tap do |declarations|
103
105
  declarations.delete(css_attr)
104
106
  end
105
107
  end
@@ -248,7 +250,7 @@ class Premailer
248
250
  # Fix for removing any CDATA tags from both style and script tags inserted per
249
251
  # https://github.com/sparklemotion/nokogiri/issues/311 and
250
252
  # https://github.com/premailer/premailer/issues/199
251
- %w(style script).each do |tag|
253
+ ['style', 'script'].each do |tag|
252
254
  doc.search(tag).children.each do |child|
253
255
  child.swap(child.text()) if child.cdata?
254
256
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # RGB helper for adapters, currently only nokogiri supported
2
3
 
3
4
  module AdapterHelper
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class Premailer
2
3
  # Manages the adapter classes. Currently supports:
3
4
  #
@@ -14,7 +15,7 @@ class Premailer
14
15
  REQUIREMENT_MAP = [
15
16
  ["nokogiri", :nokogiri],
16
17
  ["nokogiri", :nokogiri_fast],
17
- ["nokogumbo", :nokogumbo],
18
+ ["nokogumbo", :nokogumbo]
18
19
  ]
19
20
 
20
21
  # Returns the adapter to use.
@@ -42,7 +43,7 @@ class Premailer
42
43
  end
43
44
  end
44
45
 
45
- raise RuntimeError.new("No suitable adapter for Premailer was found, please install nokogiri or nokogumbo")
46
+ raise "No suitable adapter for Premailer was found, please install nokogiri or nokogumbo"
46
47
  end
47
48
 
48
49
  # Sets the adapter to use.
@@ -56,7 +57,7 @@ class Premailer
56
57
  def self.find(adapter)
57
58
  return adapter if adapter.is_a?(Module)
58
59
 
59
- Premailer::Adapter.const_get("#{adapter.to_s.split('_').map{|s| s.capitalize}.join('')}")
60
+ Premailer::Adapter.const_get("#{adapter.to_s.split('_').map{|s| s.capitalize}.join}")
60
61
  rescue NameError
61
62
  raise ArgumentError, "Invalid adapter: #{adapter}"
62
63
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  class Premailer
2
3
  class CachedRuleSet < CssParser::RuleSet
3
4
  # we call this early to find errors but css-parser calls it in .merge again
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'optparse'
2
3
  require 'premailer'
3
4
 
@@ -8,12 +9,12 @@ options = {
8
9
  :remove_classes => false,
9
10
  :verbose => false,
10
11
  :line_length => 65,
11
- :adapter => :nokogiri,
12
+ :adapter => :nokogiri
12
13
  }
13
14
 
14
15
  mode = :html
15
16
 
16
- opts = OptionParser.new do |opts|
17
+ parser = OptionParser.new do |opts|
17
18
  opts.banner = "Improve the rendering of HTML emails by making CSS inline among other things. Takes a path to a local file, a URL or a pipe as input.\n\n"
18
19
  opts.define_head "Usage: premailer <optional uri|optional path> [options]"
19
20
  opts.separator ""
@@ -79,7 +80,7 @@ opts = OptionParser.new do |opts|
79
80
  exit
80
81
  end
81
82
  end
82
- opts.parse!
83
+ parser.parse!
83
84
 
84
85
  $stderr.puts "Processing in #{mode} mode with options #{options.inspect}" if options[:verbose]
85
86
 
@@ -98,7 +99,7 @@ end
98
99
  if input
99
100
  premailer = Premailer.new(input, options)
100
101
  else
101
- puts opts
102
+ puts parser
102
103
  exit 1
103
104
  end
104
105
 
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
  require 'htmlentities'
3
4
 
4
5
  # Support functions for Premailer
@@ -13,8 +14,8 @@ module HtmlToPlainText
13
14
  #
14
15
  # TODO: add support for DL, OL
15
16
  # TODO: this is not safe and needs a real html parser to work
16
- def convert_to_text(html, line_length = 65, from_charset = 'UTF-8')
17
- txt = html
17
+ def convert_to_text(html, line_length = 65, _from_charset = 'UTF-8')
18
+ txt = +html
18
19
 
19
20
  # strip text ignored html. Useful for removing
20
21
  # headers and footers that aren't needed in the
@@ -50,7 +51,7 @@ module HtmlToPlainText
50
51
 
51
52
  if text.empty?
52
53
  ''
53
- elsif href.nil? || text.strip.downcase == href.strip.downcase
54
+ elsif href.nil? || text.strip.casecmp(href.strip) == 0
54
55
  text.strip
55
56
  else
56
57
  text.strip + ' ( ' + href.strip + ' )'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # Premailer processes HTML and CSS to improve e-mail deliverability.
2
3
  #
3
4
  # Premailer's main function is to render all CSS as inline <tt>style</tt>
@@ -15,7 +16,7 @@
15
16
  # fout.close
16
17
  #
17
18
  # # Write the plain-text output
18
- # fout = File.open("ouput.txt", "w")
19
+ # fout = File.open("output.txt", "w")
19
20
  # fout.puts premailer.to_plain_text
20
21
  # fout.close
21
22
  #
@@ -141,7 +142,7 @@ class Premailer
141
142
  include Warnings
142
143
 
143
144
  # Waning level names
144
- WARN_LABEL = %w(NONE SAFE POOR RISKY)
145
+ WARN_LABEL = ['NONE', 'SAFE', 'POOR', 'RISKY']
145
146
 
146
147
  # Create a new Premailer object.
147
148
  #
@@ -212,8 +213,7 @@ class Premailer
212
213
  :create_shorthands => true,
213
214
  :html_fragment => false,
214
215
  :adapter => Adapter.use,
215
- :drop_unmergeable_css_rules => false
216
- }.merge(options)
216
+ :drop_unmergeable_css_rules => false}.merge(options)
217
217
 
218
218
  @html_file = html
219
219
  @is_local_file = @options[:with_html_string] || Premailer.local_data?(html)
@@ -264,11 +264,11 @@ class Premailer
264
264
 
265
265
  protected
266
266
  def load_css_from_local_file!(path)
267
- css_block = ''
268
- path.gsub!(/\Afile:/, '')
267
+ css_block = +''
268
+ path.delete_prefix!('file:')
269
269
  begin
270
270
  File.open(path, "r") do |file|
271
- while line = file.gets
271
+ while (line = file.gets)
272
272
  css_block << line
273
273
  end
274
274
  end
@@ -355,11 +355,12 @@ public
355
355
  media_types.split(/[\s]+|,/).any? { |media_type| media_type.strip =~ /screen|handheld|all/i }
356
356
  end
357
357
 
358
- def append_query_string(doc, qs)
359
- return doc if qs.nil?
358
+ def append_query_string(doc, queries)
359
+ return doc if queries.nil?
360
360
 
361
- qs.to_s.gsub!(/^[\?]*/, '').strip!
362
- return doc if qs.empty?
361
+ queries = +queries
362
+ queries.to_s.gsub!(/^[\?]*/, '').strip!
363
+ return doc if queries.empty?
363
364
 
364
365
  begin
365
366
  current_host = @base_url.host
@@ -367,18 +368,18 @@ public
367
368
  current_host = nil
368
369
  end
369
370
 
370
- $stderr.puts "Attempting to append_query_string: #{qs}" if @options[:verbose]
371
+ $stderr.puts "Attempting to append_query_string: #{queries}" if @options[:verbose]
371
372
 
372
- doc.search('a').each do|el|
373
+ doc.search('a').each do |el|
373
374
  href = el.attributes['href'].to_s.strip
374
375
  next if href.nil? or href.empty?
375
376
 
376
- next if href[0,1] =~ /[\#\{\[\<\%]/ # don't bother with anchors or special-looking links
377
+ next if /[\#\{\[\<\%]/.match?(href[0,1]) # don't bother with anchors or special-looking links
377
378
 
378
379
  begin
379
380
  href = Addressable::URI.parse(href)
380
381
 
381
- if current_host and href.host != nil and href.host != current_host
382
+ if current_host and !href.host.nil? and href.host != current_host
382
383
  $stderr.puts "Skipping append_query_string for: #{href.to_s} because host is no good" if @options[:verbose]
383
384
  next
384
385
  end
@@ -390,9 +391,9 @@ public
390
391
 
391
392
  if href.query and not href.query.empty?
392
393
  amp = @options[:unescaped_ampersand] ? '&' : '&amp;'
393
- href.query = href.query + amp + qs
394
+ href.query = href.query + amp + queries
394
395
  else
395
- href.query = qs
396
+ href.query = queries
396
397
  end
397
398
 
398
399
  el['href'] = href.to_s
@@ -435,11 +436,11 @@ public
435
436
  tags.each do |tag|
436
437
  # skip links that look like they have merge tags
437
438
  # and mailto, ftp, etc...
438
- if tag.attributes[attribute].to_s =~ /^([\%\<\{\#\[]|data:|tel:|file:|sms:|callto:|facetime:|mailto:|ftp:|gopher:|cid:)/i
439
+ if /^([\%\<\{\#\[]|data:|tel:|file:|sms:|callto:|facetime:|mailto:|ftp:|gopher:|cid:)/i.match?(tag.attributes[attribute].to_s)
439
440
  next
440
441
  end
441
442
 
442
- if tag.attributes[attribute].to_s =~ /^http/i
443
+ if /^http/i.match?(tag.attributes[attribute].to_s)
443
444
  begin
444
445
  merged = Addressable::URI.parse(tag.attributes[attribute])
445
446
  rescue; next; end
@@ -473,9 +474,10 @@ public
473
474
 
474
475
  # @private
475
476
  def self.resolve_link(path, base_path) # :nodoc:
477
+ path = +path
476
478
  path.strip!
477
479
  resolved = nil
478
- if path =~ /\A(?:(https?|ftp|file):)\/\//i
480
+ if /\A(?:(https?|ftp|file):)\/\//i.match?(path)
479
481
  resolved = path
480
482
  Premailer.canonicalize(resolved)
481
483
  elsif base_path.kind_of?(Addressable::URI)
@@ -1,4 +1,5 @@
1
+ # frozen_string_literal: true
1
2
  class Premailer
2
3
  # Premailer version.
3
- VERSION = '1.23.0'.freeze
4
+ VERSION = '1.27.0'
4
5
  end
data/lib/premailer.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'yaml'
2
3
  require 'open-uri'
3
4
  require 'digest/sha2'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: premailer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.23.0
4
+ version: 1.27.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Dunae
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-05 00:00:00.000000000 Z
11
+ date: 2024-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: css_parser
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 1.12.0
19
+ version: 1.19.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 1.12.0
26
+ version: 1.19.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: htmlentities
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -129,7 +129,7 @@ dependencies:
129
129
  - !ruby/object:Gem::Version
130
130
  version: '0'
131
131
  - !ruby/object:Gem::Dependency
132
- name: coveralls
132
+ name: webmock
133
133
  requirement: !ruby/object:Gem::Requirement
134
134
  requirements:
135
135
  - - ">="
@@ -143,7 +143,7 @@ dependencies:
143
143
  - !ruby/object:Gem::Version
144
144
  version: '0'
145
145
  - !ruby/object:Gem::Dependency
146
- name: webmock
146
+ name: bump
147
147
  requirement: !ruby/object:Gem::Requirement
148
148
  requirements:
149
149
  - - ">="
@@ -157,7 +157,21 @@ dependencies:
157
157
  - !ruby/object:Gem::Version
158
158
  version: '0'
159
159
  - !ruby/object:Gem::Dependency
160
- name: bump
160
+ name: rubocop
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - "~>"
164
+ - !ruby/object:Gem::Version
165
+ version: 1.62.1
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - "~>"
171
+ - !ruby/object:Gem::Version
172
+ version: 1.62.1
173
+ - !ruby/object:Gem::Dependency
174
+ name: rubocop-performance
161
175
  requirement: !ruby/object:Gem::Requirement
162
176
  requirements:
163
177
  - - ">="