isomorfeus-mailer 2.0.0.rc2 → 2.0.0.rc6
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 +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 +31 -30
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,14 +1,14 @@
|
|
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
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-11-
|
11
|
+
date: 2021-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -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
|
@@ -72,14 +58,14 @@ dependencies:
|
|
72
58
|
requirements:
|
73
59
|
- - "~>"
|
74
60
|
- !ruby/object:Gem::Version
|
75
|
-
version: 1.3.
|
61
|
+
version: 1.3.2
|
76
62
|
type: :runtime
|
77
63
|
prerelease: false
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
79
65
|
requirements:
|
80
66
|
- - "~>"
|
81
67
|
- !ruby/object:Gem::Version
|
82
|
-
version: 1.3.
|
68
|
+
version: 1.3.2
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
70
|
name: opal-activesupport
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,70 +86,70 @@ dependencies:
|
|
100
86
|
requirements:
|
101
87
|
- - "~>"
|
102
88
|
- !ruby/object:Gem::Version
|
103
|
-
version: 0.
|
89
|
+
version: 0.14.0
|
104
90
|
type: :runtime
|
105
91
|
prerelease: false
|
106
92
|
version_requirements: !ruby/object:Gem::Requirement
|
107
93
|
requirements:
|
108
94
|
- - "~>"
|
109
95
|
- !ruby/object:Gem::Version
|
110
|
-
version: 0.
|
96
|
+
version: 0.14.0
|
111
97
|
- !ruby/object:Gem::Dependency
|
112
98
|
name: isomorfeus-preact
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
114
100
|
requirements:
|
115
101
|
- - "~>"
|
116
102
|
- !ruby/object:Gem::Version
|
117
|
-
version: 10.
|
103
|
+
version: 10.6.1
|
118
104
|
type: :runtime
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
107
|
requirements:
|
122
108
|
- - "~>"
|
123
109
|
- !ruby/object:Gem::Version
|
124
|
-
version: 10.
|
110
|
+
version: 10.6.1
|
125
111
|
- !ruby/object:Gem::Dependency
|
126
112
|
name: isomorfeus-redux
|
127
113
|
requirement: !ruby/object:Gem::Requirement
|
128
114
|
requirements:
|
129
115
|
- - "~>"
|
130
116
|
- !ruby/object:Gem::Version
|
131
|
-
version: 4.1.
|
117
|
+
version: 4.1.10
|
132
118
|
type: :runtime
|
133
119
|
prerelease: false
|
134
120
|
version_requirements: !ruby/object:Gem::Requirement
|
135
121
|
requirements:
|
136
122
|
- - "~>"
|
137
123
|
- !ruby/object:Gem::Version
|
138
|
-
version: 4.1.
|
124
|
+
version: 4.1.10
|
139
125
|
- !ruby/object:Gem::Dependency
|
140
126
|
name: isomorfeus-transport
|
141
127
|
requirement: !ruby/object:Gem::Requirement
|
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
|
@@ -184,14 +170,28 @@ dependencies:
|
|
184
170
|
requirements:
|
185
171
|
- - "~>"
|
186
172
|
- !ruby/object:Gem::Version
|
187
|
-
version: 3.
|
173
|
+
version: 3.10.0
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
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
188
|
type: :development
|
189
189
|
prerelease: false
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
191
191
|
requirements:
|
192
192
|
- - "~>"
|
193
193
|
- !ruby/object:Gem::Version
|
194
|
-
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
|