premailer 1.9.2 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4df1d858e475536189c6e91cb30d72194cf8d88b
4
- data.tar.gz: 39daad276db1125fc182e4da80ce8635debe9959
3
+ metadata.gz: 3b62798f9ef3929357e4fe01538d05615f37b9b3
4
+ data.tar.gz: f0224b7a6a42b88ebea688cf9d55fe30504f9751
5
5
  SHA512:
6
- metadata.gz: 335cb3dc57599aba6fe75eba289a250abed56b9180ffc11feb129a0b90f49d9845f92d475329dfc2ba9ec9623e69f295bc844af35a66ca790914988e0f733620
7
- data.tar.gz: d7401533fdfda12a308377cf6719e38461aafdf4c7f9b3c0eedef3998e8ef27c2126671e077d20e70aea82bb1dec3ee492b4b60545b5590e921bfb4a85628407
6
+ metadata.gz: 96bfa7a6374f3cd91f6004a8a988d46e789bd2cce29e12f595fee64c0e86244236e77766b1380a347329dbd71866f487ca23f9aedab0d600b2cf1a54a1c3253f
7
+ data.tar.gz: 09148edbb09bee950ad6e5c7c97709587b862136a38b5f484ab8e5f039f92f137ce7b948303796480004b31018e0f4ebe488d68c4ae1767f0f61d141d11f8db7
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Premailer README [![Build Status](https://travis-ci.org/premailer/premailer.png?branch=master)](https://travis-ci.org/premailer/premailer)
1
+ # Premailer README [![Build Status](https://travis-ci.org/premailer/premailer.png?branch=master)](https://travis-ci.org/premailer/premailer) [![Gem Version](https://badge.fury.io/rb/premailer.svg)](https://badge.fury.io/rb/premailer)
2
2
 
3
3
  ## What is this?
4
4
 
@@ -50,14 +50,13 @@ end
50
50
 
51
51
  ## Adapters
52
52
 
53
- Premailer's default adapter is nokogiri if both nokogiri and hpricot are included in the Gemfile list. However, if you want to use a different adapter, you can choose to.
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
54
 
55
- There are four adapters in total (as of premailer 1.9.1)
55
+ There are three adapters in total (as of premailer 1.9.1)
56
56
 
57
57
  1. nokogiri (default)
58
58
  2. nokogiri_fast
59
59
  3. nokogumbo
60
- 4. hpricot (deprecated and will be removed in future premailer releases)
61
60
 
62
61
  `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,
63
62
 
@@ -113,5 +112,5 @@ and to [Campaign Monitor](https://www.campaignmonitor.com/) for supporting the w
113
112
 
114
113
  The source code can be found on [GitHub](https://github.com/premailer/premailer).
115
114
 
116
- Copyright by Alex Dunae (dunae.ca, e-mail 'code' at the same domain), 2007-2017. See [LICENSE.md](https://github.com/alexdunae/premailer/blob/master/LICENSE.md) for license details.
115
+ 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.
117
116
 
@@ -4,10 +4,8 @@ class Premailer
4
4
  # * nokogiri
5
5
  # * nokogiri_fast
6
6
  # * nokogumbo
7
- # * hpricot
8
7
  module Adapter
9
8
 
10
- autoload :Hpricot, 'premailer/adapter/hpricot'
11
9
  autoload :Nokogiri, 'premailer/adapter/nokogiri'
12
10
  autoload :NokogiriFast, 'premailer/adapter/nokogiri_fast'
13
11
  autoload :Nokogumbo, 'premailer/adapter/nokogumbo'
@@ -17,7 +15,6 @@ class Premailer
17
15
  ["nokogiri", :nokogiri],
18
16
  ["nokogiri", :nokogiri_fast],
19
17
  ["nokogumbo", :nokogumbo],
20
- ["hpricot", :hpricot],
21
18
  ]
22
19
 
23
20
  # Returns the adapter to use.
@@ -35,7 +32,6 @@ class Premailer
35
32
  return :nokogiri if defined?(::Nokogiri)
36
33
  return :nokogiri_fast if defined?(::NokogiriFast)
37
34
  return :nokogumbo if defined?(::Nokogumbo)
38
- return :hpricot if defined?(::Hpricot)
39
35
 
40
36
  REQUIREMENT_MAP.each do |(library, adapter)|
41
37
  begin
@@ -46,7 +42,7 @@ class Premailer
46
42
  end
47
43
  end
48
44
 
49
- raise RuntimeError.new("No suitable adapter for Premailer was found, please install hpricot or nokogiri")
45
+ raise RuntimeError.new("No suitable adapter for Premailer was found, please install nokogiri or nokogumbo")
50
46
  end
51
47
 
52
48
  # Sets the adapter to use.
@@ -144,25 +144,19 @@ class Premailer
144
144
  end
145
145
 
146
146
  # Create a <tt>style</tt> element with un-mergable rules (e.g. <tt>:hover</tt>)
147
- # and write it into the <tt>body</tt>.
147
+ # and write it into the <tt>head</tt>.
148
148
  #
149
149
  # <tt>doc</tt> is an Nokogiri document and <tt>unmergable_css_rules</tt> is a Css::RuleSet.
150
150
  #
151
151
  # @return [::Nokogiri::XML] a document.
152
152
  def write_unmergable_css_rules(doc, unmergable_rules) # :nodoc:
153
153
  styles = unmergable_rules.to_s
154
-
155
154
  unless styles.empty?
156
- style_tag = "<style type=\"text/css\">\n#{styles}</style>"
157
- unless (body = doc.search('body')).empty?
158
- if doc.at_css('body').children && !doc.at_css('body').children.empty?
159
- doc.at_css('body').children.before(::Nokogiri::XML.fragment(style_tag))
160
- else
161
- doc.at_css('body').add_child(::Nokogiri::XML.fragment(style_tag))
162
- end
163
- else
164
- doc.inner_html = style_tag += doc.inner_html
165
- end
155
+ style_tag = doc.create_element "style", "#{styles}"
156
+ head = doc.at_css('head')
157
+ head ||= doc.root.first_element_child.add_previous_sibling(doc.create_element "head") if doc.root && doc.root.first_element_child
158
+ head ||= doc.add_child(doc.create_element "head")
159
+ head << style_tag
166
160
  end
167
161
  doc
168
162
  end
@@ -146,26 +146,19 @@ class Premailer
146
146
  end
147
147
 
148
148
  # Create a <tt>style</tt> element with un-mergable rules (e.g. <tt>:hover</tt>)
149
- # and write it into the <tt>body</tt>.
149
+ # and write it into the <tt>head</tt>.
150
150
  #
151
151
  # <tt>doc</tt> is an Nokogiri document and <tt>unmergable_css_rules</tt> is a Css::RuleSet.
152
152
  #
153
153
  # @return [::Nokogiri::XML] a document.
154
154
  def write_unmergable_css_rules(doc, unmergable_rules) # :nodoc:
155
155
  styles = unmergable_rules.to_s
156
-
157
- unless styles.empty?
158
- style_tag = "<style type=\"text/css\">\n#{styles}</style>"
159
- unless (body = doc.search('body')).empty?
160
- if doc.at_css('body').children && !doc.at_css('body').children.empty?
161
- doc.at_css('body').children.before(::Nokogiri::XML.fragment(style_tag))
162
- else
163
- doc.at_css('body').add_child(::Nokogiri::XML.fragment(style_tag))
164
- end
165
- else
166
- doc.inner_html = style_tag += doc.inner_html
167
- end
168
- end
156
+ return doc if styles.empty?
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
169
162
  doc
170
163
  end
171
164
 
@@ -143,26 +143,19 @@ class Premailer
143
143
  end
144
144
 
145
145
  # Create a <tt>style</tt> element with un-mergable rules (e.g. <tt>:hover</tt>)
146
- # and write it into the <tt>body</tt>.
146
+ # and write it into the <tt>head</tt>.
147
147
  #
148
148
  # <tt>doc</tt> is an Nokogiri document and <tt>unmergable_css_rules</tt> is a Css::RuleSet.
149
149
  #
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
-
154
- unless styles.empty?
155
- style_tag = "<style type=\"text/css\">\n#{styles}</style>"
156
- unless (body = doc.search('body')).empty?
157
- if doc.at_css('body').children && !doc.at_css('body').children.empty?
158
- doc.at_css('body').children.before(::Nokogiri::XML.fragment(style_tag))
159
- else
160
- doc.at_css('body').add_child(::Nokogiri::XML.fragment(style_tag))
161
- end
162
- else
163
- doc.inner_html = style_tag += doc.inner_html
164
- end
165
- end
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
166
159
  doc
167
160
  end
168
161
 
@@ -3,11 +3,12 @@ require 'premailer'
3
3
 
4
4
  # defaults
5
5
  options = {
6
- :base_url => nil,
6
+ :base_url => nil,
7
7
  :link_query_string => nil,
8
- :remove_classes => false,
9
- :verbose => false,
10
- :line_length => 65
8
+ :remove_classes => false,
9
+ :verbose => false,
10
+ :line_length => 65,
11
+ :adapter => :nokogiri,
11
12
  }
12
13
 
13
14
  mode = :html
@@ -28,6 +29,10 @@ opts = OptionParser.new do |opts|
28
29
  mode = v
29
30
  end
30
31
 
32
+ opts.on("--adapter ADAPTER", [:nokogiri, :nokogiri_fast, :nokogumbo], "Adapter: nokogiri, nokogiri_fast or nokogumbo (default: #{options[:adapter]}") do |v|
33
+ options[:adapter] = v
34
+ end
35
+
31
36
  opts.on("-b", "--base-url STRING", String, "Base URL, useful for local files") do |v|
32
37
  options[:base_url] = v
33
38
  end
@@ -40,12 +45,12 @@ opts = OptionParser.new do |opts|
40
45
  options[:css] = v
41
46
  end
42
47
 
43
- opts.on("-r", "--remove-classes", "Remove HTML classes") do |v|
44
- options[:remove_classes] = v
48
+ opts.on("-r", "--remove-classes", "Remove HTML classes") do
49
+ options[:remove_classes] = true
45
50
  end
46
51
 
47
- opts.on("-j", "--remove-scripts", "Remove <script> elements") do |v|
48
- options[:remove_scripts] = v
52
+ opts.on("-j", "--remove-scripts", "Remove <script> elements") do
53
+ options[:remove_scripts] = true
49
54
  end
50
55
 
51
56
  opts.on("-l", "--line-length N", Integer, "Line length for plaintext (default: #{options[:line_length].to_s})") do |v|
@@ -56,12 +61,12 @@ opts = OptionParser.new do |opts|
56
61
  options[:output_encoding] = "US-ASCII"
57
62
  end
58
63
 
59
- opts.on("-d", "--io-exceptions", "Abort on I/O errors") do |v|
60
- options[:io_exceptions] = v
64
+ opts.on("-d", "--io-exceptions", "Abort on I/O errors") do
65
+ options[:io_exceptions] = true
61
66
  end
62
67
 
63
- opts.on("-v", "--verbose", "Print additional information at runtime") do |v|
64
- options[:verbose] = v
68
+ opts.on("-v", "--verbose", "Print additional information at runtime") do
69
+ options[:verbose] = true
65
70
  end
66
71
 
67
72
  opts.on_tail("-?", "--help", "Show this message") do
@@ -121,10 +121,10 @@ class Premailer
121
121
  # unmergeable CSS rules to be preserved in the head (CssParser)
122
122
  attr_reader :unmergable_rules
123
123
 
124
- # processed HTML document (Hpricot/Nokogiri)
124
+ # processed HTML document (Nokogiri/Nokogumbo)
125
125
  attr_reader :processed_doc
126
126
 
127
- # source HTML document (Hpricot/Nokogiri)
127
+ # source HTML document (Nokogiri/Nokogumbo)
128
128
  attr_reader :doc
129
129
 
130
130
  # Warning levels
@@ -174,7 +174,7 @@ class Premailer
174
174
  # @option options [String] :input_encoding Manually specify the source documents encoding. This is a good idea. Default is ASCII-8BIT.
175
175
  # @option options [Boolean] :replace_html_entities Convert HTML entities to actual characters. Default is false.
176
176
  # @option options [Boolean] :escape_url_attributes URL Escapes href, src, and background attributes on elements. Default is true.
177
- # @option options [Symbol] :adapter Which HTML parser to use, either <tt>:nokogiri</tt> or <tt>:hpricot</tt>. Default is <tt>:hpricot</tt>.
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
180
  def initialize(html, options = {})
@@ -411,9 +411,9 @@ public
411
411
  # Processes <tt>href</tt> <tt>src</tt> and <tt>background</tt> attributes
412
412
  # as well as CSS <tt>url()</tt> declarations found in inline <tt>style</tt> attributes.
413
413
  #
414
- # <tt>doc</tt> is an Hpricot document and <tt>base_uri</tt> is either a string or a URI.
414
+ # <tt>doc</tt> is a document and <tt>base_uri</tt> is either a string or a URI.
415
415
  #
416
- # Returns an Hpricot document.
416
+ # Returns a document.
417
417
  def convert_inline_links(doc, base_uri) # :nodoc:
418
418
  base_uri = URI.parse(base_uri) unless base_uri.kind_of?(URI)
419
419
 
@@ -1,4 +1,4 @@
1
1
  class Premailer
2
2
  # Premailer version.
3
- VERSION = '1.9.2'.freeze
3
+ VERSION = '1.10.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.9.2
4
+ version: 1.10.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-02-03 00:00:00.000000000 Z
11
+ date: 2017-02-22 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.8
19
+ version: 1.4.9
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.8
26
+ version: 1.4.9
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: htmlentities
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -42,14 +42,14 @@ dependencies:
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '1.3'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.3'
55
55
  - !ruby/object:Gem::Dependency
@@ -72,40 +72,20 @@ dependencies:
72
72
  - - "!="
73
73
  - !ruby/object:Gem::Version
74
74
  version: 0.9.0
75
- - !ruby/object:Gem::Dependency
76
- name: hpricot
77
- requirement: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- version: 0.8.3
82
- type: :development
83
- prerelease: false
84
- version_requirements: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - ">="
87
- - !ruby/object:Gem::Version
88
- version: 0.8.3
89
75
  - !ruby/object:Gem::Dependency
90
76
  name: nokogiri
91
77
  requirement: !ruby/object:Gem::Requirement
92
78
  requirements:
93
- - - ">="
94
- - !ruby/object:Gem::Version
95
- version: 1.4.4
96
- - - "<="
79
+ - - "~>"
97
80
  - !ruby/object:Gem::Version
98
- version: 1.6.8
81
+ version: '1.7'
99
82
  type: :development
100
83
  prerelease: false
101
84
  version_requirements: !ruby/object:Gem::Requirement
102
85
  requirements:
103
- - - ">="
104
- - !ruby/object:Gem::Version
105
- version: 1.4.4
106
- - - "<="
86
+ - - "~>"
107
87
  - !ruby/object:Gem::Version
108
- version: 1.6.8
88
+ version: '1.7'
109
89
  - !ruby/object:Gem::Dependency
110
90
  name: yard
111
91
  requirement: !ruby/object:Gem::Requirement
@@ -192,7 +172,7 @@ dependencies:
192
172
  version: '0'
193
173
  description: Improve the rendering of HTML emails by making CSS inline, converting
194
174
  links and warning about unsupported code.
195
- email: code@dunae.ca
175
+ email: akzhan.abdulin@gmail.com
196
176
  executables:
197
177
  - premailer
198
178
  extensions: []
@@ -203,7 +183,6 @@ files:
203
183
  - bin/premailer
204
184
  - lib/premailer.rb
205
185
  - lib/premailer/adapter.rb
206
- - lib/premailer/adapter/hpricot.rb
207
186
  - lib/premailer/adapter/nokogiri.rb
208
187
  - lib/premailer/adapter/nokogiri_fast.rb
209
188
  - lib/premailer/adapter/nokogumbo.rb
@@ -213,7 +192,7 @@ files:
213
192
  - lib/premailer/premailer.rb
214
193
  - lib/premailer/version.rb
215
194
  - misc/client_support.yaml
216
- homepage: http://premailer.dialect.ca/
195
+ homepage: https://github.com/premailer/premailer
217
196
  licenses: []
218
197
  metadata:
219
198
  yard.run: yri
@@ -225,7 +204,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
225
204
  requirements:
226
205
  - - ">="
227
206
  - !ruby/object:Gem::Version
228
- version: 2.0.0
207
+ version: 2.1.0
229
208
  required_rubygems_version: !ruby/object:Gem::Requirement
230
209
  requirements:
231
210
  - - ">="
@@ -233,7 +212,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
233
212
  version: '0'
234
213
  requirements: []
235
214
  rubyforge_project:
236
- rubygems_version: 2.6.8
215
+ rubygems_version: 2.5.1
237
216
  signing_key:
238
217
  specification_version: 4
239
218
  summary: Preflight for HTML e-mail.
@@ -1,220 +0,0 @@
1
- require 'hpricot'
2
-
3
- class Premailer
4
- module Adapter
5
- # Hpricot adapter
6
- module Hpricot
7
- include AdapterHelper::RgbToHex
8
-
9
- def self.included(base)
10
- warn <<eos
11
- [DEPRECATED] Premailer's Hpricot adapter will be removed with the next major \
12
- release. Change your :adapter option to :nokogiri or remove the `hpricot` gem \
13
- from your application to silence this warning. (Called from #{caller[2]})
14
- eos
15
- end
16
-
17
- # Merge CSS into the HTML document.
18
- # @return [String] HTML.
19
- def to_inline_css
20
- doc = @processed_doc
21
- @unmergable_rules = CssParser::Parser.new
22
-
23
- # Give all styles already in style attributes a specificity of 1000
24
- # per http://www.w3.org/TR/CSS21/cascade.html#specificity
25
- doc.search("*[@style]").each do |el|
26
- el['style'] = '[SPEC=1000[' + el.attributes['style'] + ']]'
27
- end
28
-
29
- # Iterate through the rules and merge them into the HTML
30
- @css_parser.each_selector(:all) do |selector, declaration, specificity, media_types|
31
- # Save un-mergable rules separately
32
- selector.gsub!(/:link([\s]*)+/i) {|m| $1 }
33
-
34
- # Convert element names to lower case
35
- selector.gsub!(/([\s]|^)([\w]+)/) {|m| $1.to_s + $2.to_s.downcase }
36
-
37
- if Premailer.is_media_query?(media_types) || selector =~ Premailer::RE_UNMERGABLE_SELECTORS
38
- @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selector, declaration), media_types) unless @options[:preserve_styles]
39
- else
40
- begin
41
- if selector =~ Premailer::RE_RESET_SELECTORS
42
- # this is in place to preserve the MailChimp CSS reset: http://github.com/mailchimp/Email-Blueprints/
43
- # however, this doesn't mean for testing pur
44
- @unmergable_rules.add_rule_set!(CssParser::RuleSet.new(selector, declaration)) unless !@options[:preserve_reset]
45
- end
46
-
47
- # Change single ID CSS selectors into xpath so that we can match more
48
- # than one element. Added to work around dodgy generated code.
49
- selector.gsub!(/\A\#([\w_\-]+)\Z/, '*[@id=\1]')
50
-
51
- # convert attribute selectors to hpricot's format
52
- selector.gsub!(/\[([\w]+)\]/, '[@\1]')
53
- selector.gsub!(/\[([\w]+)([\=\~\^\$\*]+)([\w\s]+)\]/, '[@\1\2\'\3\']')
54
-
55
- doc.search(selector).each do |el|
56
- if el.elem? and (el.name != 'head' and el.parent.name != 'head')
57
- # Add a style attribute or append to the existing one
58
- block = "[SPEC=#{specificity}[#{declaration}]]"
59
- el['style'] = (el.attributes['style'].to_s ||= '') + ' ' + block
60
- end
61
- end
62
- rescue ::Hpricot::Error, RuntimeError, ArgumentError
63
- $stderr.puts "CSS syntax error with selector: #{selector}" if @options[:verbose]
64
- next
65
- end
66
- end
67
- end
68
-
69
- # Remove script tags
70
- if @options[:remove_scripts]
71
- doc.search("script").remove
72
- end
73
-
74
- # Read STYLE attributes and perform folding
75
- doc.search("*[@style]").each do |el|
76
- style = el.attributes['style'].to_s
77
-
78
- declarations = []
79
-
80
- style.scan(/\[SPEC\=([\d]+)\[(.[^\]\]]*)\]\]/).each do |declaration|
81
- rs = CssParser::RuleSet.new(nil, declaration[1].to_s, declaration[0].to_i)
82
- declarations << rs
83
- end
84
- # Perform style folding
85
- merged = CssParser.merge(declarations)
86
- merged.expand_shorthand!
87
- merged.create_shorthand! if @options[:create_shorthands]
88
-
89
- # Duplicate CSS attributes as HTML attributes
90
- if Premailer::RELATED_ATTRIBUTES.has_key?(el.name) && @options[:css_to_attributes]
91
- Premailer::RELATED_ATTRIBUTES[el.name].each do |css_att, html_att|
92
- if el[html_att].nil? and not merged[css_att].empty?
93
- new_html_att = merged[css_att].gsub(/url\(['|"](.*)['|"]\)/, '\1').gsub(/;$|\s*!important/, '').strip
94
- el[html_att] = css_att.end_with?('color') && @options[:rgb_to_hex_attributes] ? ensure_hex(new_html_att) : new_html_att
95
- end
96
- merged.instance_variable_get("@declarations").tap do |declarations|
97
- unless @options[:preserve_style_attribute]
98
- declarations.delete(css_att)
99
- end
100
- end
101
- end
102
- end
103
-
104
- # write the inline STYLE attribute
105
- el['style'] = Premailer.escape_string(merged.declarations_to_s)
106
- end
107
-
108
- doc = write_unmergable_css_rules(doc, @unmergable_rules)
109
-
110
- if @options[:remove_classes] or @options[:remove_comments]
111
- doc.search('*').each do |el|
112
- if el.comment? and @options[:remove_comments]
113
- lst = el.parent.children
114
- el.parent = nil
115
- lst.delete(el)
116
- elsif el.elem?
117
- el.remove_attribute('class') if @options[:remove_classes]
118
- end
119
- end
120
- end
121
-
122
- if @options[:reset_contenteditable]
123
- doc.search('*[@contenteditable]').each do |el|
124
- el.remove_attribute('contenteditable')
125
- end
126
- end
127
-
128
- if @options[:remove_ids]
129
- # find all anchor's targets and hash them
130
- targets = []
131
- doc.search("a[@href^='#']").each do |el|
132
- target = el.get_attribute('href')[1..-1]
133
- targets << target
134
- el.set_attribute('href', "#" + Digest::MD5.hexdigest(target))
135
- end
136
- # hash ids that are links target, delete others
137
- doc.search("*[@id]").each do |el|
138
- id = el.get_attribute('id')
139
- if targets.include?(id)
140
- el.set_attribute('id', Digest::MD5.hexdigest(id))
141
- else
142
- el.remove_attribute('id')
143
- end
144
- end
145
- end
146
-
147
- @processed_doc = doc
148
-
149
- @processed_doc.to_original_html
150
- end
151
-
152
- # Create a <tt>style</tt> element with un-mergable rules (e.g. <tt>:hover</tt>)
153
- # and write it into the <tt>body</tt>.
154
- #
155
- # <tt>doc</tt> is an Hpricot document and <tt>unmergable_css_rules</tt> is a Css::RuleSet.
156
- #
157
- # @return [::Hpricot] a document.
158
- def write_unmergable_css_rules(doc, unmergable_rules) # :nodoc:
159
- styles = unmergable_rules.to_s
160
-
161
- unless styles.empty?
162
- style_tag = "\n<style type=\"text/css\">\n#{styles}</style>\n"
163
- if head = doc.search('head')
164
- head.append(style_tag)
165
- elsif body = doc.search('body')
166
- body.append(style_tag)
167
- else
168
- doc.inner_html= doc.inner_html << style_tag
169
- end
170
- end
171
- doc
172
- end
173
-
174
-
175
- # Converts the HTML document to a format suitable for plain-text e-mail.
176
- #
177
- # If present, uses the <body> element as its base; otherwise uses the whole document.
178
- #
179
- # @return [String] Plain text.
180
- def to_plain_text
181
- html_src = ''
182
- begin
183
- html_src = @doc.search("body").inner_html
184
- rescue; end
185
-
186
- html_src = @doc.to_html unless html_src and not html_src.empty?
187
- convert_to_text(html_src, @options[:line_length], @html_encoding)
188
- end
189
-
190
-
191
- # Gets the original HTML as a string.
192
- # @return [String] HTML.
193
- def to_s
194
- @doc.to_original_html
195
- end
196
-
197
- # Load the HTML file and convert it into an Hpricot document.
198
- #
199
- # @return [::Hpricot] a document.
200
- def load_html(input) # :nodoc:
201
- thing = nil
202
-
203
- # TODO: duplicate options
204
- if @options[:with_html_string] or @options[:inline] or input.respond_to?(:read)
205
- thing = input
206
- elsif @is_local_file
207
- @base_dir = File.dirname(input)
208
- thing = File.open(input, 'r')
209
- else
210
- thing = open(input)
211
- end
212
-
213
- # TODO: deal with Hpricot seg faults on empty input
214
- thing ? Hpricot(thing) : nil
215
- end
216
-
217
- end
218
- end
219
- end
220
-