isomorfeus-mailer 2.0.0.rc5 → 2.0.0.rc6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +4 -0
- data/lib/isomorfeus/html2text.rb +268 -0
- data/lib/isomorfeus/mailer/version.rb +1 -1
- data/lib/isomorfeus-mailer.rb +2 -1
- metadata +20 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 98507154da2d33348d785c83bfec5f8260aa0fd93b945c8cbb6ae87f7f0391ce
|
4
|
+
data.tar.gz: 9a9255bb1f5dea7fd0b079db6e71ecd12db31ae7c0a0db5c941ad49439dcda3f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68a4488a9a5aed3f102aa208c28f5ff084b7a6af9b08c7af6877b7695fed0b35d8f0396520e44d6916d5cea417c138978ba638b38ec483a4af37886d43ffb9c8
|
7
|
+
data.tar.gz: 7a0219c4a75ae76886ba4fc9ca8719413a1b1b8ec276c96b70ba21aa15c3c3b323e9c25dea979c7fc1b50a0dbd4497dc89269169ee5cb299b234996ef573ed8a
|
data/LICENSE
CHANGED
@@ -19,3 +19,7 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
21
|
SOFTWARE.
|
22
|
+
|
23
|
+
file lib/isomorfeus/html2text.rb originally taken from https://github.com/soundasleep/html2text_ruby:
|
24
|
+
|
25
|
+
MIT License as above, Copyright 2015 Jevon Wright
|
@@ -0,0 +1,268 @@
|
|
1
|
+
class Html2Text
|
2
|
+
VERSION = "0.3.1"
|
3
|
+
|
4
|
+
attr_reader :doc
|
5
|
+
|
6
|
+
def initialize(doc)
|
7
|
+
@doc = doc
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.convert(html)
|
11
|
+
html = html.to_s
|
12
|
+
|
13
|
+
if is_office_document?(html)
|
14
|
+
# Emulate the CSS rendering of Office documents
|
15
|
+
html = html.gsub("<p class=MsoNormal>", "<br>")
|
16
|
+
.gsub("<o:p> </o:p>", "<br>")
|
17
|
+
.gsub("<o:p></o:p>", "")
|
18
|
+
end
|
19
|
+
|
20
|
+
if !html.include?("<html")
|
21
|
+
# Stop Nokogiri from inserting in <p> tags
|
22
|
+
html = "<div>#{html}</div>"
|
23
|
+
end
|
24
|
+
|
25
|
+
html = fix_newlines(replace_entities(html))
|
26
|
+
doc = Nokogiri::HTML(html)
|
27
|
+
|
28
|
+
Html2Text.new(doc).convert
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.fix_newlines(text)
|
32
|
+
text.gsub("\r\n", "\n").gsub("\r", "\n")
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.replace_entities(text)
|
36
|
+
text.gsub(" ", " ").gsub("\u00a0", " ").gsub("‌", "")
|
37
|
+
end
|
38
|
+
|
39
|
+
def convert
|
40
|
+
output = iterate_over(doc)
|
41
|
+
output = remove_leading_and_trailing_whitespace(output)
|
42
|
+
output = remove_unnecessary_empty_lines(output)
|
43
|
+
return output.strip
|
44
|
+
end
|
45
|
+
|
46
|
+
DO_NOT_TOUCH_WHITESPACE = "<do-not-touch-whitespace>"
|
47
|
+
|
48
|
+
def remove_leading_and_trailing_whitespace(text)
|
49
|
+
# ignore any <pre> blocks, which we don't want to interact with
|
50
|
+
pre_blocks = text.split(DO_NOT_TOUCH_WHITESPACE)
|
51
|
+
|
52
|
+
output = []
|
53
|
+
pre_blocks.each.with_index do |block, index|
|
54
|
+
if index % 2 == 0
|
55
|
+
output << block.gsub(/[ \t]*\n[ \t]*/im, "\n").gsub(/ *\t */im, "\t")
|
56
|
+
else
|
57
|
+
output << block
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
output.join("")
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def self.is_office_document?(text)
|
67
|
+
text.include?("urn:schemas-microsoft-com:office")
|
68
|
+
end
|
69
|
+
|
70
|
+
def remove_unnecessary_empty_lines(text)
|
71
|
+
text.gsub(/\n\n\n*/im, "\n\n")
|
72
|
+
end
|
73
|
+
|
74
|
+
def trimmed_whitespace(text)
|
75
|
+
# Replace whitespace characters with a space (equivalent to \s)
|
76
|
+
# and force any text encoding into UTF-8
|
77
|
+
if text.valid_encoding?
|
78
|
+
text.gsub(/[\t\n\f\r ]+/im, " ")
|
79
|
+
else
|
80
|
+
text.force_encoding("WINDOWS-1252")
|
81
|
+
return trimmed_whitespace(text.encode("UTF-16be", invalid: :replace, replace: "?").encode('UTF-8'))
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def iterate_over(node)
|
86
|
+
return "\n" if node.name.downcase == "br" && next_node_is_text?(node)
|
87
|
+
|
88
|
+
return trimmed_whitespace(node.text) if node.text?
|
89
|
+
|
90
|
+
if ["style", "head", "title", "meta", "script"].include?(node.name.downcase)
|
91
|
+
return ""
|
92
|
+
end
|
93
|
+
|
94
|
+
if node.name.downcase == "pre"
|
95
|
+
return "\n#{DO_NOT_TOUCH_WHITESPACE}#{node.text}#{DO_NOT_TOUCH_WHITESPACE}"
|
96
|
+
end
|
97
|
+
|
98
|
+
output = []
|
99
|
+
|
100
|
+
output << prefix_whitespace(node)
|
101
|
+
output += node.children.map do |child|
|
102
|
+
if !child.name.nil?
|
103
|
+
iterate_over(child)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
output << suffix_whitespace(node)
|
107
|
+
|
108
|
+
output = output.compact.join("") || ""
|
109
|
+
|
110
|
+
if !node.name.nil?
|
111
|
+
if node.name.downcase == "a"
|
112
|
+
output = wrap_link(node, output)
|
113
|
+
elsif node.name.downcase == "img"
|
114
|
+
output = image_text(node)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
return output
|
119
|
+
end
|
120
|
+
|
121
|
+
def prefix_whitespace(node)
|
122
|
+
case node.name.downcase
|
123
|
+
when "hr"
|
124
|
+
"\n---------------------------------------------------------------\n"
|
125
|
+
|
126
|
+
when "h1", "h2", "h3", "h4", "h5", "h6", "ol", "ul"
|
127
|
+
"\n\n"
|
128
|
+
|
129
|
+
when "p"
|
130
|
+
"\n\n"
|
131
|
+
|
132
|
+
when "tr"
|
133
|
+
"\n"
|
134
|
+
|
135
|
+
when "div"
|
136
|
+
if node.parent.name == "div" && (node.parent.text.strip == node.text.strip)
|
137
|
+
""
|
138
|
+
else
|
139
|
+
"\n"
|
140
|
+
end
|
141
|
+
|
142
|
+
when "td", "th"
|
143
|
+
"\t"
|
144
|
+
|
145
|
+
when "li"
|
146
|
+
"- "
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def suffix_whitespace(node)
|
151
|
+
case node.name.downcase
|
152
|
+
when "h1", "h2", "h3", "h4", "h5", "h6"
|
153
|
+
# add another line
|
154
|
+
"\n\n"
|
155
|
+
|
156
|
+
when "p"
|
157
|
+
"\n\n"
|
158
|
+
|
159
|
+
when "br"
|
160
|
+
if next_node_name(node) != "div" && next_node_name(node) != nil
|
161
|
+
"\n"
|
162
|
+
end
|
163
|
+
|
164
|
+
when "li"
|
165
|
+
"\n"
|
166
|
+
|
167
|
+
when "div"
|
168
|
+
if next_node_is_text?(node)
|
169
|
+
"\n"
|
170
|
+
elsif next_node_name(node) != "div" && next_node_name(node) != nil
|
171
|
+
"\n"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# links are returned in [text](link) format
|
177
|
+
def wrap_link(node, output)
|
178
|
+
href = node.attribute("href")
|
179
|
+
name = node.attribute("name")
|
180
|
+
|
181
|
+
output = output.strip
|
182
|
+
|
183
|
+
# remove double [[ ]]s from linking images
|
184
|
+
if output[0] == "[" && output[-1] == "]"
|
185
|
+
output = output[1, output.length - 2]
|
186
|
+
|
187
|
+
# for linking images, the title of the <a> overrides the title of the <img>
|
188
|
+
if node.attribute("title")
|
189
|
+
output = node.attribute("title").to_s
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# if there is no link text, but a title attr
|
194
|
+
if output.empty? && node.attribute("title")
|
195
|
+
output = node.attribute("title").to_s
|
196
|
+
end
|
197
|
+
|
198
|
+
if href.nil?
|
199
|
+
if !name.nil?
|
200
|
+
output = "[#{output}]"
|
201
|
+
end
|
202
|
+
else
|
203
|
+
href = href.to_s
|
204
|
+
|
205
|
+
if href != output && href != "mailto:#{output}" &&
|
206
|
+
href != "http://#{output}" && href != "https://#{output}"
|
207
|
+
if output.empty?
|
208
|
+
output = href
|
209
|
+
else
|
210
|
+
output = "[#{output}](#{href})"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
case next_node_name(node)
|
216
|
+
when "h1", "h2", "h3", "h4", "h5", "h6"
|
217
|
+
output += "\n"
|
218
|
+
end
|
219
|
+
|
220
|
+
output
|
221
|
+
end
|
222
|
+
|
223
|
+
def image_text(node)
|
224
|
+
if node.attribute("title")
|
225
|
+
"[" + node.attribute("title").to_s + "]"
|
226
|
+
elsif node.attribute("alt")
|
227
|
+
"[" + node.attribute("alt").to_s + "]"
|
228
|
+
else
|
229
|
+
""
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def next_node_name(node)
|
234
|
+
next_node = node.next_sibling
|
235
|
+
while next_node != nil
|
236
|
+
break if next_node.element?
|
237
|
+
next_node = next_node.next_sibling
|
238
|
+
end
|
239
|
+
|
240
|
+
if next_node && next_node.element?
|
241
|
+
next_node.name.downcase
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def next_node_is_text?(node)
|
246
|
+
return !node.next_sibling.nil? && node.next_sibling.text? && !node.next_sibling.text.strip.empty?
|
247
|
+
end
|
248
|
+
|
249
|
+
def previous_node_name(node)
|
250
|
+
previous_node = node.previous_sibling
|
251
|
+
while previous_node != nil
|
252
|
+
break if previous_node.element?
|
253
|
+
previous_node = previous_node.previous_sibling
|
254
|
+
end
|
255
|
+
|
256
|
+
if previous_node && previous_node.element?
|
257
|
+
previous_node.name.downcase
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def previous_node_is_text?(node)
|
262
|
+
return !node.previous_sibling.nil? && node.previous_sibling.text? && !node.previous_sibling.text.strip.empty?
|
263
|
+
end
|
264
|
+
|
265
|
+
# def previous_node_is_not_text?(node)
|
266
|
+
# return node.previous_sibling.nil? || !node.previous_sibling.text? || node.previous_sibling.text.strip.empty?
|
267
|
+
# end
|
268
|
+
end
|
data/lib/isomorfeus-mailer.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: isomorfeus-mailer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.
|
4
|
+
version: 2.0.0.rc6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Biedermann
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '6.1'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: html2text
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 0.3.1
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: 0.3.1
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: mailhandler
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,28 +128,28 @@ dependencies:
|
|
142
128
|
requirements:
|
143
129
|
- - '='
|
144
130
|
- !ruby/object:Gem::Version
|
145
|
-
version: 2.0.0.
|
131
|
+
version: 2.0.0.rc6
|
146
132
|
type: :runtime
|
147
133
|
prerelease: false
|
148
134
|
version_requirements: !ruby/object:Gem::Requirement
|
149
135
|
requirements:
|
150
136
|
- - '='
|
151
137
|
- !ruby/object:Gem::Version
|
152
|
-
version: 2.0.0.
|
138
|
+
version: 2.0.0.rc6
|
153
139
|
- !ruby/object:Gem::Dependency
|
154
140
|
name: isomorfeus
|
155
141
|
requirement: !ruby/object:Gem::Requirement
|
156
142
|
requirements:
|
157
143
|
- - '='
|
158
144
|
- !ruby/object:Gem::Version
|
159
|
-
version: 2.0.0.
|
145
|
+
version: 2.0.0.rc6
|
160
146
|
type: :development
|
161
147
|
prerelease: false
|
162
148
|
version_requirements: !ruby/object:Gem::Requirement
|
163
149
|
requirements:
|
164
150
|
- - '='
|
165
151
|
- !ruby/object:Gem::Version
|
166
|
-
version: 2.0.0.
|
152
|
+
version: 2.0.0.rc6
|
167
153
|
- !ruby/object:Gem::Dependency
|
168
154
|
name: rake
|
169
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -192,6 +178,20 @@ dependencies:
|
|
192
178
|
- - "~>"
|
193
179
|
- !ruby/object:Gem::Version
|
194
180
|
version: 3.10.0
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: rspec-collection_matchers
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - "~>"
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: 1.2.0
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - "~>"
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: 1.2.0
|
195
195
|
description: Write mail template components and send mail.
|
196
196
|
email: jan@kursator.de
|
197
197
|
executables: []
|
@@ -201,6 +201,7 @@ files:
|
|
201
201
|
- LICENSE
|
202
202
|
- README.md
|
203
203
|
- lib/isomorfeus-mailer.rb
|
204
|
+
- lib/isomorfeus/html2text.rb
|
204
205
|
- lib/isomorfeus/mailer/config.rb
|
205
206
|
- lib/isomorfeus/mailer/imports.rb
|
206
207
|
- lib/isomorfeus/mailer/version.rb
|