premailer 1.12.0 → 1.29.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.
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ class Premailer
3
+ class CachedRuleSet < CssParser::RuleSet
4
+ # we call this early to find errors but css-parser calls it in .merge again
5
+ # so to prevent slowdown and bugs we refuse to run it twice on the same ruleset
6
+ # ideally should be upstreamed into css-parser
7
+ def expand_shorthand!
8
+ super unless @expand_shorthand
9
+ ensure
10
+ @expand_shorthand = true
11
+ end
12
+ end
13
+ end
@@ -1,19 +1,20 @@
1
+ # frozen_string_literal: true
1
2
  require 'optparse'
2
3
  require 'premailer'
3
4
 
4
5
  # defaults
5
6
  options = {
6
- :base_url => nil,
7
+ :base_url => nil,
7
8
  :link_query_string => nil,
8
- :remove_classes => false,
9
- :verbose => false,
10
- :line_length => 65,
11
- :adapter => :nokogiri,
9
+ :remove_classes => false,
10
+ :verbose => false,
11
+ :line_length => 65,
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 ""
@@ -53,11 +54,11 @@ opts = OptionParser.new do |opts|
53
54
  options[:remove_scripts] = true
54
55
  end
55
56
 
56
- opts.on("-l", "--line-length N", Integer, "Line length for plaintext (default: #{options[:line_length].to_s})") do |v|
57
+ opts.on("-l", "--line-length N", Integer, "Line length for plaintext (default: #{options[:line_length]})") do |v|
57
58
  options[:line_length] = v
58
59
  end
59
60
 
60
- opts.on("-e", "--entities", "Output HTML entities instead of UTF-8 when using Nokogiri") do |v|
61
+ opts.on("-e", "--entities", "Output HTML entities instead of UTF-8 when using Nokogiri") do |_v|
61
62
  options[:output_encoding] = "US-ASCII"
62
63
  end
63
64
 
@@ -79,9 +80,9 @@ opts = OptionParser.new do |opts|
79
80
  exit
80
81
  end
81
82
  end
82
- opts.parse!
83
+ parser.parse!
83
84
 
84
- $stderr.puts "Processing in #{mode} mode with options #{options.inspect}" if options[:verbose]
85
+ warn "Processing in #{mode} mode with options #{options.inspect}" if options[:verbose]
85
86
 
86
87
  premailer = nil
87
88
  input = nil
@@ -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,19 +1,19 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
2
  require 'htmlentities'
3
3
 
4
4
  # Support functions for Premailer
5
5
  module HtmlToPlainText
6
-
7
6
  # Returns the text in UTF-8 format with all HTML tags removed
8
- #
9
- # HTML content can be omitted from the output by surrounding it in the following comments:
7
+ #
8
+ # HTML content can be omitted from the output by surrounding it in the following comments:
10
9
  #
11
10
  # <!-- start text/html -->
12
11
  # <!-- end text/html -->
13
12
  #
14
13
  # TODO: add support for DL, OL
15
- def convert_to_text(html, line_length = 65, from_charset = 'UTF-8')
16
- txt = html
14
+ # TODO: this is not safe and needs a real html parser to work
15
+ def convert_to_text(html, line_length = 65, _from_charset = 'UTF-8')
16
+ txt = +html
17
17
 
18
18
  # strip text ignored html. Useful for removing
19
19
  # headers and footers that aren't needed in the
@@ -26,43 +26,39 @@ module HtmlToPlainText
26
26
  # eg. the following formats:
27
27
  # <img alt="" />
28
28
  # <img alt="">
29
- txt.gsub!(/<img.+?alt=\"([^\"]*)\"[^>]*\>/i, '\1')
29
+ txt.gsub!(/<img[^>]+?alt="([^"]*)"[^>]*>/i, '\1')
30
30
 
31
31
  # for img tags with '' for attribute quotes
32
32
  # with or without closing tag
33
33
  # eg. the following formats:
34
34
  # <img alt='' />
35
35
  # <img alt=''>
36
- txt.gsub!(/<img.+?alt=\'([^\']*)\'[^>]*\>/i, '\1')
36
+ txt.gsub!(/<img[^>]+?alt='([^']*)'[^>]*>/i, '\1')
37
37
 
38
38
  # remove script tags and content
39
- txt.gsub!(/<script.*\/script>/m, '')
39
+ txt.gsub!(/<script.*?\/script>/m, '')
40
40
 
41
- # links with double quotes
42
- txt.gsub!(/<a\s[^\n]*?href=["'](mailto:)?([^"]*)["][^>]*>(.*?)<\/a>/im) do |s|
43
- if $3.empty?
44
- ''
45
- elsif $3.strip.downcase == $2.strip.downcase
46
- $3.strip
47
- else
48
- $3.strip + ' ( ' + $2.strip + ' )'
41
+ # links
42
+ txt.gsub!(/<a\s+([^>]+)>(.*?)<\/a>/im) do |s|
43
+ text = $2.strip
44
+
45
+ match = /href=(['"])(?:mailto:)?(.+?)\1/.match(s)
46
+ if match
47
+ href = match[2]
49
48
  end
50
- end
51
49
 
52
- # links with single quotes
53
- txt.gsub!(/<a\s[^\n]*?href=["'](mailto:)?([^']*)['][^>]*>(.*?)<\/a>/im) do |s|
54
- if $3.empty?
50
+ if text.empty?
55
51
  ''
56
- elsif $3.strip.downcase == $2.strip.downcase
57
- $3.strip
52
+ elsif href.nil? || text.strip.casecmp(href.strip) == 0
53
+ text.strip
58
54
  else
59
- $3.strip + ' ( ' + $2.strip + ' )'
55
+ text.strip + ' ( ' + href.strip + ' )'
60
56
  end
61
57
  end
62
58
 
63
59
  # handle headings (H1-H6)
64
60
  txt.gsub!(/(<\/h[1-6]>)/i, "\n\\1") # move closing tags to new lines
65
- txt.gsub!(/[\s]*<h([1-6]+)[^>]*>[\s]*(.*)[\s]*<\/h[1-6]+>/i) do |s|
61
+ txt.gsub!(/[\s]*<h([1-6]+)[^>]*>[\s]*(.*)[\s]*<\/h[1-6]+>/i) do |_s|
66
62
  hlevel = $1.to_i
67
63
 
68
64
  htext = $2
@@ -71,17 +67,21 @@ module HtmlToPlainText
71
67
 
72
68
  # determine maximum line length
73
69
  hlength = 0
74
- htext.each_line { |l| llength = l.strip.length; hlength = llength if llength > hlength }
70
+ htext.each_line do |l|
71
+ llength = l.strip.length
72
+ hlength = llength if llength > hlength
73
+ end
75
74
  hlength = line_length if hlength > line_length
76
75
 
77
- case hlevel
76
+ htext =
77
+ case hlevel
78
78
  when 1 # H1, asterisks above and below
79
- htext = ('*' * hlength) + "\n" + htext + "\n" + ('*' * hlength)
79
+ ('*' * hlength) + "\n" + htext + "\n" + ('*' * hlength)
80
80
  when 2 # H1, dashes above and below
81
- htext = ('-' * hlength) + "\n" + htext + "\n" + ('-' * hlength)
82
- else # H3-H6, dashes below
83
- htext = htext + "\n" + ('-' * hlength)
84
- end
81
+ ('-' * hlength) + "\n" + htext + "\n" + ('-' * hlength)
82
+ else # H3-H6, dashes below
83
+ htext + "\n" + ('-' * hlength)
84
+ end
85
85
 
86
86
  "\n\n" + htext + "\n\n"
87
87
  end
@@ -120,8 +120,8 @@ module HtmlToPlainText
120
120
  txt.gsub!(/[\n]{3,}/, "\n\n")
121
121
 
122
122
  # the word messes up the parens
123
- txt.gsub!(/\(([ \n])(http[^)]+)([\n ])\)/) do |s|
124
- ($1 == "\n" ? $1 : '' ) + '( ' + $2 + ' )' + ($3 == "\n" ? $1 : '' )
123
+ txt.gsub!(/\(([ \n])(http[^)]+)([\n ])\)/) do |_s|
124
+ ($1 == "\n" ? $1 : '') + '( ' + $2 + ' )' + ($3 == "\n" ? $1 : '')
125
125
  end
126
126
 
127
127
  txt.strip