premailer 1.10.2 → 1.12.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
- SHA1:
3
- metadata.gz: 74e7a6a6abc466e9c0e113d5231d4e4a85d84cb2
4
- data.tar.gz: 4c59b4febdbcc9f24bb02a1e97f4daac68417b35
2
+ SHA256:
3
+ metadata.gz: 6d3e8552d269ddef67b722b192f58c2afe242f6a824a07e4e7fd4e5bbc3f57f2
4
+ data.tar.gz: 6c6b611237ffe68b655654c75c21c7a8f17bc73ca9502e06891f26ab5b1bb583
5
5
  SHA512:
6
- metadata.gz: 20aa057a4fb25ab0bae43093b9ba32e1dc8c64f5e37bb9b9666f57c854b971516bf2a84e2e0402d85c1ccf698a89213b3461ebab5bdfed4bd7bc68a881ed1366
7
- data.tar.gz: 60ef76babcda83da01f605c2188e15bb611b0c89b1a1de66ab01212dd2567c283fcf2328fe538215883c12670483c3f107a4625a9cf4956faf489b8294164997
6
+ metadata.gz: 1c963172a6abcb9e71824c07e54a80ea89c58fda395349d68ea0567a5fa06cf160663bd1e8a169a81532f5ad3b7c97d8ed0ad2c09a4182c3d281982a878348da
7
+ data.tar.gz: 758dae24fbd064a1ee44fe4ab6f0537c191826474dc045a8af5354f28a17e4d20e8a56e93d2ea3ebab83ab4c9c9b2376aa0b53467ff50338773e78e815b8ccbe
data/README.md CHANGED
@@ -12,7 +12,7 @@ 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 is created (optional)
15
+ * A [plain text version](https://premailer.github.io/premailer/HtmlToPlainText.html) is created (optional)
16
16
 
17
17
  ## Installation
18
18
 
@@ -80,6 +80,7 @@ Premailer looks for a few CSS attributes that make working with tables a bit eas
80
80
  | -premailer-height | Available on `table`, `tr`, `th` and `td` elements |
81
81
  | -premailer-cellpadding | Available on `table` elements |
82
82
  | -premailer-cellspacing | Available on `table` elements |
83
+ | -premailer-align | Available on `table` elements |
83
84
  | data-premailer="ignore" | Available on `link` and `style` elements. Premailer will ignore these elements entirely. |
84
85
 
85
86
  Each of these CSS declarations will be copied to appropriate element's attribute.
@@ -94,7 +94,7 @@ class Premailer
94
94
  el['style'] = merged.declarations_to_s
95
95
  end
96
96
 
97
- doc = write_unmergable_css_rules(doc, @unmergable_rules)
97
+ doc = write_unmergable_css_rules(doc, @unmergable_rules) unless @options[:drop_unmergeable_css_rules]
98
98
 
99
99
  if @options[:remove_classes] or @options[:remove_comments]
100
100
  doc.traverse do |el|
@@ -149,11 +149,17 @@ class Premailer
149
149
  def write_unmergable_css_rules(doc, unmergable_rules) # :nodoc:
150
150
  styles = unmergable_rules.to_s
151
151
  unless styles.empty?
152
- style_tag = doc.create_element "style", "#{styles}"
153
- head = doc.at_css('head')
154
- head ||= doc.root.first_element_child.add_previous_sibling(doc.create_element "head") if doc.root && doc.root.first_element_child
155
- head ||= doc.add_child(doc.create_element "head")
156
- head << style_tag
152
+ if @options[:html_fragment]
153
+ style_tag = ::Nokogiri::XML::Node.new("style", doc)
154
+ style_tag.content = styles
155
+ doc.add_child(style_tag)
156
+ else
157
+ style_tag = doc.create_element "style", "#{styles}"
158
+ head = doc.at_css('head')
159
+ head ||= doc.root.first_element_child.add_previous_sibling(doc.create_element "head") if doc.root && doc.root.first_element_child
160
+ head ||= doc.add_child(doc.create_element "head")
161
+ head << style_tag
162
+ end
157
163
  end
158
164
  doc
159
165
  end
@@ -216,12 +222,16 @@ class Premailer
216
222
  end
217
223
  # Default encoding is ASCII-8BIT (binary) per http://groups.google.com/group/nokogiri-talk/msg/0b81ef0dc180dc74
218
224
  # However, we really don't want to hardcode this. ASCII-8BIT should be the default, but not the only option.
219
- if thing.is_a?(String) and RUBY_VERSION =~ /1.9/
225
+ encoding = if thing.is_a?(String) and RUBY_VERSION =~ /1.9/
220
226
  thing = thing.force_encoding(@options[:input_encoding]).encode!
221
- doc = ::Nokogiri::HTML(thing, nil, @options[:input_encoding]) { |c| c.recover }
227
+ @options[:input_encoding]
228
+ else
229
+ @options[:input_encoding] || (RUBY_PLATFORM == 'java' ? nil : 'BINARY')
230
+ end
231
+ doc = if @options[:html_fragment]
232
+ ::Nokogiri::HTML.fragment(thing, encoding)
222
233
  else
223
- default_encoding = RUBY_PLATFORM == 'java' ? nil : 'BINARY'
224
- doc = ::Nokogiri::HTML(thing, nil, @options[:input_encoding] || default_encoding) { |c| c.recover }
234
+ ::Nokogiri::HTML(thing, nil, encoding) { |c| c.recover }
225
235
  end
226
236
 
227
237
  # Fix for removing any CDATA tags from both style and script tags inserted per
@@ -96,7 +96,7 @@ class Premailer
96
96
  el['style'] = merged.declarations_to_s
97
97
  end
98
98
 
99
- doc = write_unmergable_css_rules(doc, @unmergable_rules)
99
+ doc = write_unmergable_css_rules(doc, @unmergable_rules) unless @options[:drop_unmergeable_css_rules]
100
100
 
101
101
  if @options[:remove_classes] or @options[:remove_comments]
102
102
  doc.traverse do |el|
@@ -150,12 +150,19 @@ class Premailer
150
150
  # @return [::Nokogiri::XML] a document.
151
151
  def write_unmergable_css_rules(doc, unmergable_rules) # :nodoc:
152
152
  styles = unmergable_rules.to_s
153
- return doc if styles.empty?
154
- style_tag = doc.create_element "style", styles
155
- head = doc.at_css('head')
156
- head ||= doc.root.first_element_child.add_previous_sibling(doc.create_element "head") if doc.root && doc.root.first_element_child
157
- head ||= doc.add_child(doc.create_element "head")
158
- head << style_tag
153
+ unless styles.empty?
154
+ if @options[:html_fragment]
155
+ style_tag = ::Nokogiri::XML::Node.new("style", doc)
156
+ style_tag.content = styles
157
+ doc.add_child(style_tag)
158
+ else
159
+ style_tag = doc.create_element "style", styles
160
+ head = doc.at_css('head')
161
+ head ||= doc.root.first_element_child.add_previous_sibling(doc.create_element "head") if doc.root && doc.root.first_element_child
162
+ head ||= doc.add_child(doc.create_element "head")
163
+ head << style_tag
164
+ end
165
+ end
159
166
  doc
160
167
  end
161
168
 
@@ -217,12 +224,16 @@ class Premailer
217
224
  end
218
225
  # Default encoding is ASCII-8BIT (binary) per http://groups.google.com/group/nokogiri-talk/msg/0b81ef0dc180dc74
219
226
  # However, we really don't want to hardcode this. ASCII-8BIT should be the default, but not the only option.
220
- if thing.is_a?(String) and RUBY_VERSION =~ /1.9/
227
+ encoding = if thing.is_a?(String) and RUBY_VERSION =~ /1.9/
221
228
  thing = thing.force_encoding(@options[:input_encoding]).encode!
222
- doc = ::Nokogiri::HTML(thing, nil, @options[:input_encoding]) { |c| c.recover }
229
+ @options[:input_encoding]
230
+ else
231
+ @options[:input_encoding] || (RUBY_PLATFORM == 'java' ? nil : 'BINARY')
232
+ end
233
+ doc = if @options[:html_fragment]
234
+ ::Nokogiri::HTML.fragment(thing, encoding)
223
235
  else
224
- default_encoding = RUBY_PLATFORM == 'java' ? nil : 'BINARY'
225
- doc = ::Nokogiri::HTML(thing, nil, @options[:input_encoding] || default_encoding) { |c| c.recover }
236
+ ::Nokogiri::HTML(thing, nil, encoding) { |c| c.recover }
226
237
  end
227
238
 
228
239
  # Fix for removing any CDATA tags from both style and script tags inserted per
@@ -94,7 +94,7 @@ class Premailer
94
94
  el['style'] = merged.declarations_to_s
95
95
  end
96
96
 
97
- doc = write_unmergable_css_rules(doc, @unmergable_rules)
97
+ doc = write_unmergable_css_rules(doc, @unmergable_rules) unless @options[:drop_unmergeable_css_rules]
98
98
 
99
99
  if @options[:remove_classes] or @options[:remove_comments]
100
100
  doc.traverse do |el|
@@ -148,12 +148,19 @@ class Premailer
148
148
  # @return [::Nokogiri::XML] a document.
149
149
  def write_unmergable_css_rules(doc, unmergable_rules) # :nodoc:
150
150
  styles = unmergable_rules.to_s
151
- return doc if styles.empty?
152
- style_tag = doc.create_element "style", styles
153
- head = doc.at_css('head')
154
- head ||= doc.root.first_element_child.add_previous_sibling(doc.create_element "head") if doc.root && doc.root.first_element_child
155
- head ||= doc.add_child(doc.create_element "head")
156
- head << style_tag
151
+ unless styles.empty?
152
+ if @options[:html_fragment]
153
+ style_tag = ::Nokogiri::XML::Node.new("style", doc)
154
+ style_tag.content = styles
155
+ doc.add_child(style_tag)
156
+ else
157
+ style_tag = doc.create_element "style", styles
158
+ head = doc.at_css('head')
159
+ head ||= doc.root.first_element_child.add_previous_sibling(doc.create_element "head") if doc.root && doc.root.first_element_child
160
+ head ||= doc.add_child(doc.create_element "head")
161
+ head << style_tag
162
+ end
163
+ end
157
164
  doc
158
165
  end
159
166
 
@@ -217,10 +224,11 @@ class Premailer
217
224
  # However, we really don't want to hardcode this. ASCII-8BIT should be the default, but not the only option.
218
225
  if thing.is_a?(String) and RUBY_VERSION =~ /1.9/
219
226
  thing = thing.force_encoding(@options[:input_encoding]).encode!
220
- doc = ::Nokogiri::HTML5(thing)
227
+ end
228
+ doc = if @options[:html_fragment]
229
+ ::Nokogiri::HTML5.fragment(thing)
221
230
  else
222
- default_encoding = RUBY_PLATFORM == 'java' ? nil : 'BINARY'
223
- doc = ::Nokogiri::HTML5(thing)
231
+ ::Nokogiri::HTML5(thing)
224
232
  end
225
233
 
226
234
  # Fix for removing any CDATA tags from both style and script tags inserted per
@@ -5,6 +5,11 @@ require 'htmlentities'
5
5
  module HtmlToPlainText
6
6
 
7
7
  # 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:
10
+ #
11
+ # <!-- start text/html -->
12
+ # <!-- end text/html -->
8
13
  #
9
14
  # TODO: add support for DL, OL
10
15
  def convert_to_text(html, line_length = 65, from_charset = 'UTF-8')
@@ -30,8 +35,22 @@ module HtmlToPlainText
30
35
  # <img alt=''>
31
36
  txt.gsub!(/<img.+?alt=\'([^\']*)\'[^>]*\>/i, '\1')
32
37
 
33
- # links
34
- txt.gsub!(/<a\s.*?href=["'](mailto:)?([^"']*)["'][^>]*>((.|\s)*?)<\/a>/i) do |s|
38
+ # remove script tags and content
39
+ txt.gsub!(/<script.*\/script>/m, '')
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 + ' )'
49
+ end
50
+ end
51
+
52
+ # links with single quotes
53
+ txt.gsub!(/<a\s[^\n]*?href=["'](mailto:)?([^']*)['][^>]*>(.*?)<\/a>/im) do |s|
35
54
  if $3.empty?
36
55
  ''
37
56
  elsif $3.strip.downcase == $2.strip.downcase
@@ -86,9 +105,7 @@ module HtmlToPlainText
86
105
  he = HTMLEntities.new
87
106
  txt = he.decode(txt)
88
107
 
89
- # no more than two consecutive spaces
90
- txt.gsub!(/ {2,}/, " ")
91
-
108
+ # word wrap
92
109
  txt = word_wrap(txt, line_length)
93
110
 
94
111
  # remove linefeeds (\r\n and \r -> \n)
@@ -151,14 +151,14 @@ class Premailer
151
151
  #
152
152
  # @param [Hash] options the options to handle html with.
153
153
  # @option options [Fixnum] :line_length Line length used by to_plain_text. Default is 65.
154
- # @option options [Fixnum] :warn_level What level of CSS compatibility warnings to show (see {Premailer::Warnings}).
154
+ # @option options [Fixnum] :warn_level What level of CSS compatibility warnings to show (see {Premailer::Warnings}, default is Warnings::SAFE).
155
155
  # @option options [String] :link_query_string A string to append to every <tt>a href=""</tt> link. Do not include the initial <tt>?</tt>.
156
156
  # @option options [String] :base_url Used to calculate absolute URLs for local files.
157
157
  # @option options [Array(String)] :css Manually specify CSS stylesheets.
158
- # @option options [Boolean] :css_to_attributes Copy related CSS attributes into HTML attributes (e.g. background-color to bgcolor)
158
+ # @option options [Boolean] :css_to_attributes Copy related CSS attributes into HTML attributes (e.g. background-color to bgcolor). Default is true.
159
159
  # @option options [Boolean] :preserve_style_attribute Preserve original style attribute
160
160
  # @option options [String] :css_string Pass CSS as a string
161
- # @option options [Boolean] :rgb_to_hex_attributes Convert RBG to Hex colors, default false
161
+ # @option options [Boolean] :rgb_to_hex_attributes Convert RBG to Hex colors. Default is false.
162
162
  # @option options [Boolean] :remove_ids Remove ID attributes whenever possible and convert IDs used as anchors to hashed to avoid collisions in webmail programs. Default is false.
163
163
  # @option options [Boolean] :remove_classes Remove class attributes. Default is false.
164
164
  # @option options [Boolean] :remove_comments Remove html comments. Default is false.
@@ -177,6 +177,8 @@ class Premailer
177
177
  # @option options [Symbol] :adapter Which HTML parser to use, <tt>:nokogiri</tt>, <tt>:nokogiri_fast</tt> or <tt>:nokogumbo</tt>. Default is <tt>:nokogiri</tt>.
178
178
  # @option options [String] :output_encoding Output encoding option for Nokogiri adapter. Should be set to "US-ASCII" to output HTML entities instead of Unicode characters.
179
179
  # @option options [Boolean] :create_shorthands Combine several properties into a shorthand one, e.g. font: style weight size. Default is true.
180
+ # @option options [Boolean] :html_fragment Handle HTML fragment without any HTML content wrappers. Default is false.
181
+ # @option options [Boolean] :drop_unmergeable_css_rules Do not include unmergeable css rules in a <tt><style><tt> tag. Default is false.
180
182
  def initialize(html, options = {})
181
183
  @options = {:warn_level => Warnings::SAFE,
182
184
  :line_length => 65,
@@ -206,7 +208,9 @@ class Premailer
206
208
  :escape_url_attributes => true,
207
209
  :unescaped_ampersand => false,
208
210
  :create_shorthands => true,
211
+ :html_fragment => false,
209
212
  :adapter => Adapter.use,
213
+ :drop_unmergeable_css_rules => false
210
214
  }.merge(options)
211
215
 
212
216
  @html_file = html
@@ -234,7 +238,7 @@ class Premailer
234
238
 
235
239
  @adapter_class = Adapter.find @options[:adapter]
236
240
 
237
- self.class.send(:include, @adapter_class)
241
+ self.extend(@adapter_class)
238
242
 
239
243
  @doc = load_html(@html_file)
240
244
 
@@ -400,7 +404,7 @@ public
400
404
 
401
405
  # Check for an XHTML doctype
402
406
  def is_xhtml?
403
- intro = @doc.to_html.strip.split("\n")[0..2].join(' ')
407
+ intro = @doc.to_xhtml.strip.split("\n")[0..2].join(' ')
404
408
  is_xhtml = !!(intro =~ /w3c\/\/[\s]*dtd[\s]+xhtml/i)
405
409
  $stderr.puts "Is XHTML? #{is_xhtml.inspect}\nChecked:\n#{intro}" if @options[:debug]
406
410
  is_xhtml
@@ -464,11 +468,6 @@ public
464
468
  media_types && media_types.any?{|mt| mt.to_s.count('()') >= 2 }
465
469
  end
466
470
 
467
- # @private
468
- def self.escape_string(str) # :nodoc:
469
- str.gsub(/"/ , "'")
470
- end
471
-
472
471
  # @private
473
472
  def self.resolve_link(path, base_path) # :nodoc:
474
473
  path.strip!
@@ -492,9 +491,7 @@ public
492
491
  #
493
492
  # IO objects return true, as do strings that look like URLs.
494
493
  def self.local_data?(data)
495
- return true if data.is_a?(IO) || data.is_a?(StringIO)
496
- return true if data =~ /\Afile:\/\//i
497
- return false if data =~ /\A(?:(https?|ftp):)\/\//i
494
+ return false if data.kind_of?(String) && data =~ /\A(?:(https?|ftp):)\/\//i
498
495
  true
499
496
  end
500
497
 
@@ -1,4 +1,4 @@
1
1
  class Premailer
2
2
  # Premailer version.
3
- VERSION = '1.10.2'.freeze
3
+ VERSION = '1.12.0'.freeze
4
4
  end
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.10.2
4
+ version: 1.12.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: 2017-03-10 00:00:00.000000000 Z
11
+ date: 2020-07-11 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.4.10
19
+ version: 1.6.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.4.10
26
+ version: 1.6.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: htmlentities
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -92,28 +92,14 @@ dependencies:
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: '1.7'
95
+ version: 1.8.2
96
96
  type: :development
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: '1.7'
103
- - !ruby/object:Gem::Dependency
104
- name: yard
105
- requirement: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - ">="
108
- - !ruby/object:Gem::Version
109
- version: '0'
110
- type: :development
111
- prerelease: false
112
- version_requirements: !ruby/object:Gem::Requirement
113
- requirements:
114
- - - ">="
115
- - !ruby/object:Gem::Version
116
- version: '0'
102
+ version: 1.8.2
117
103
  - !ruby/object:Gem::Dependency
118
104
  name: redcarpet
119
105
  requirement: !ruby/object:Gem::Requirement
@@ -184,6 +170,20 @@ dependencies:
184
170
  - - ">="
185
171
  - !ruby/object:Gem::Version
186
172
  version: '0'
173
+ - !ruby/object:Gem::Dependency
174
+ name: bump
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ type: :development
181
+ prerelease: false
182
+ version_requirements: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
187
  description: Improve the rendering of HTML emails by making CSS inline, converting
188
188
  links and warning about unsupported code.
189
189
  email: akzhan.abdulin@gmail.com
@@ -218,15 +218,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
218
218
  requirements:
219
219
  - - ">="
220
220
  - !ruby/object:Gem::Version
221
- version: 2.1.0
221
+ version: 2.3.0
222
222
  required_rubygems_version: !ruby/object:Gem::Requirement
223
223
  requirements:
224
224
  - - ">="
225
225
  - !ruby/object:Gem::Version
226
226
  version: '0'
227
227
  requirements: []
228
- rubyforge_project:
229
- rubygems_version: 2.6.8
228
+ rubygems_version: 3.1.3
230
229
  signing_key:
231
230
  specification_version: 4
232
231
  summary: Preflight for HTML e-mail.