email_reply_parser 0.5.9 → 0.5.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +1 -1
- data/email_reply_parser.gemspec +6 -36
- data/lib/email_reply_parser.rb +4 -10
- data/test/email_reply_parser_test.rb +38 -28
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1d5b9fdfe30fe4feec4e1b84c68b25180b5da4cbe6aa8cebae7d7b725c6918c6
|
4
|
+
data.tar.gz: e046ee4ce446ee8a54d2e669ae1cd10bc0ae7e5f9e55c28d439991f7c8311965
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e4680771a08970cf019ad1bbeb7a2de56b34df351cca6a6a10aaeebff681eff71e4e2fce7809667ab9e5d1505506d5835d8e180dae731825c97a1ef3ae30cf8
|
7
|
+
data.tar.gz: cef0b121c8c201116348fa880274191b1020ed189c11b0c49a8f13e5d00b619a40aeac8eafe1fb09e908e9ff179d3b47692212364192fe3d7adde33a2c6cfc5f
|
data/README.md
CHANGED
data/email_reply_parser.gemspec
CHANGED
@@ -1,60 +1,33 @@
|
|
1
1
|
$LOAD_PATH.unshift '.'
|
2
2
|
require 'lib/email_reply_parser'
|
3
3
|
|
4
|
-
## This is the rakegem gemspec template. Make sure you read and understand
|
5
|
-
## all of the comments. Some sections require modification, and others can
|
6
|
-
## be deleted if you don't need them. Once you understand the contents of
|
7
|
-
## this file, feel free to delete any comments that begin with two hash marks.
|
8
|
-
## You can find comprehensive Gem::Specification documentation, at
|
9
|
-
## http://docs.rubygems.org/read/chapter/20
|
10
4
|
Gem::Specification.new do |s|
|
11
5
|
s.specification_version = 2 if s.respond_to? :specification_version=
|
12
6
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
13
7
|
s.rubygems_version = '1.3.5'
|
8
|
+
s.license = 'MIT'
|
14
9
|
|
15
|
-
## Leave these as is they will be modified for you by the rake gemspec task.
|
16
|
-
## If your rubyforge_project name is different, then edit it and comment out
|
17
|
-
## the sub! line in the Rakefile
|
18
10
|
s.name = 'email_reply_parser'
|
19
11
|
s.version = EmailReplyParser::VERSION
|
20
12
|
s.date = Time.now.strftime('%Y-%m-%d')
|
21
|
-
s.rubyforge_project = 'email_reply_parser'
|
22
13
|
|
23
|
-
|
24
|
-
|
25
|
-
s.
|
26
|
-
|
14
|
+
s.summary = "EmailReplyParser is a small library to parse plain text " \
|
15
|
+
"email content."
|
16
|
+
s.description = "EmailReplyParser is a small library to parse plain text " \
|
17
|
+
"email content. This is what GitHub uses to display comments " \
|
18
|
+
"that were created from email replies."
|
27
19
|
|
28
|
-
## List the primary authors. If there are a bunch of authors, it's probably
|
29
|
-
## better to set the email to an email list or something. If you don't have
|
30
|
-
## a custom homepage, consider using your GitHub URL or the like.
|
31
20
|
s.authors = ["Rick Olson"]
|
32
21
|
s.email = 'technoweenie@gmail.com'
|
33
22
|
s.homepage = 'http://github.com/github/email_reply_parser'
|
34
23
|
|
35
|
-
## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as
|
36
|
-
## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb'
|
37
24
|
s.require_paths = %w[lib]
|
38
25
|
|
39
|
-
## This sections is only necessary if you have C extensions.
|
40
|
-
#s.require_paths << 'ext'
|
41
|
-
#s.extensions = %w[ext/extconf.rb]
|
42
|
-
|
43
|
-
## If your gem includes any executables, list them here.
|
44
|
-
#s.executables = ["name"]
|
45
|
-
#s.default_executable = 'name'
|
46
|
-
|
47
|
-
## Specify any RDoc options here. You'll want to add your README and
|
48
|
-
## LICENSE files to the extra_rdoc_files list.
|
49
26
|
s.rdoc_options = ["--charset=UTF-8"]
|
50
27
|
s.extra_rdoc_files = %w[README.md LICENSE]
|
51
28
|
|
52
|
-
## List your runtime dependencies here. Runtime dependencies are those
|
53
|
-
## that are needed for an end user to actually USE your code.
|
54
29
|
#s.add_dependency('DEPNAME', [">= 1.1.0", "< 2.0.0"])
|
55
30
|
|
56
|
-
## List your development dependencies here. Development dependencies are
|
57
|
-
## those that are only needed during development
|
58
31
|
#s.add_development_dependency('DEVDEPNAME', [">= 1.1.0", "< 2.0.0"])
|
59
32
|
|
60
33
|
## Leave this section as-is. It will be automatically generated from the
|
@@ -93,8 +66,5 @@ Gem::Specification.new do |s|
|
|
93
66
|
]
|
94
67
|
# = MANIFEST =
|
95
68
|
|
96
|
-
## Test files will be grabbed from the file list. Make sure the path glob
|
97
|
-
## matches what you actually use.
|
98
69
|
s.test_files = s.files.select { |path| path =~ /^test\/.*_test\.rb/ }
|
99
70
|
end
|
100
|
-
|
data/lib/email_reply_parser.rb
CHANGED
@@ -30,7 +30,7 @@ require 'strscan'
|
|
30
30
|
#
|
31
31
|
# [mail]: https://github.com/mikel/mail
|
32
32
|
class EmailReplyParser
|
33
|
-
VERSION = "0.5.
|
33
|
+
VERSION = "0.5.10"
|
34
34
|
|
35
35
|
# Public: Splits an email body into a list of Fragments.
|
36
36
|
#
|
@@ -132,14 +132,8 @@ class EmailReplyParser
|
|
132
132
|
|
133
133
|
private
|
134
134
|
EMPTY = "".freeze
|
135
|
-
SIGNATURE = '(?m)(--\s*$|__\s*$|\w-$)|(^(\w+\s
|
136
|
-
|
137
|
-
begin
|
138
|
-
require 're2'
|
139
|
-
SIG_REGEX = RE2::Regexp.new(SIGNATURE)
|
140
|
-
rescue LoadError
|
141
|
-
SIG_REGEX = Regexp.new(SIGNATURE)
|
142
|
-
end
|
135
|
+
SIGNATURE = '(?m)(--\s*$|__\s*$|\w-$)|(^(\w+\s+){1,3}ym morf tneS$)'
|
136
|
+
SIG_REGEX = Regexp.new(SIGNATURE)
|
143
137
|
|
144
138
|
### Line-by-Line Parsing
|
145
139
|
|
@@ -188,7 +182,7 @@ class EmailReplyParser
|
|
188
182
|
#
|
189
183
|
# Returns true if the line is a valid header, or false.
|
190
184
|
def quote_header?(line)
|
191
|
-
line =~ /^:etorw.*nO$/
|
185
|
+
line =~ /^:etorw.*nO$/ || line =~ /^.*:(morF|tneS|oT|tcejbuS)$/
|
192
186
|
end
|
193
187
|
|
194
188
|
# Builds the fragment string and reverses it, after all lines have been
|
@@ -50,10 +50,10 @@ I am currently using the Java HTTP API.\n", reply.fragments[0].to_s
|
|
50
50
|
assert_equal [false, true, false, false, true],
|
51
51
|
reply.fragments.map { |f| f.signature? }
|
52
52
|
|
53
|
-
assert_match
|
54
|
-
assert_match
|
55
|
-
assert_match
|
56
|
-
assert_match
|
53
|
+
assert_match(/^Oh thanks.\n\nHaving/, reply.fragments[0].to_s)
|
54
|
+
assert_match(/^-A/, reply.fragments[1].to_s)
|
55
|
+
assert_match(/^On [^\:]+\:/, reply.fragments[2].to_s)
|
56
|
+
assert_match(/^_/, reply.fragments[4].to_s)
|
57
57
|
end
|
58
58
|
|
59
59
|
def test_reads_bottom_post
|
@@ -68,10 +68,10 @@ I am currently using the Java HTTP API.\n", reply.fragments[0].to_s
|
|
68
68
|
reply.fragments.map { |f| f.hidden? }
|
69
69
|
|
70
70
|
assert_equal "Hi,", reply.fragments[0].to_s
|
71
|
-
assert_match
|
72
|
-
assert_match
|
73
|
-
assert_match
|
74
|
-
assert_match
|
71
|
+
assert_match(/^On [^\:]+\:/, reply.fragments[1].to_s)
|
72
|
+
assert_match(/^You can list/, reply.fragments[2].to_s)
|
73
|
+
assert_match(/^> /, reply.fragments[3].to_s)
|
74
|
+
assert_match(/^_/, reply.fragments[5].to_s)
|
75
75
|
end
|
76
76
|
|
77
77
|
def test_reads_inline_replies
|
@@ -85,11 +85,11 @@ I am currently using the Java HTTP API.\n", reply.fragments[0].to_s
|
|
85
85
|
assert_equal [false, false, false, false, true, true, true],
|
86
86
|
reply.fragments.map { |f| f.hidden? }
|
87
87
|
|
88
|
-
assert_match
|
89
|
-
assert_match
|
88
|
+
assert_match(/^On [^\:]+\:/, reply.fragments[0].to_s)
|
89
|
+
assert_match(/^I will reply/, reply.fragments[1].to_s)
|
90
90
|
assert_match "okay?", reply.fragments[2].to_s
|
91
|
-
assert_match
|
92
|
-
assert_match
|
91
|
+
assert_match(/^and under this./, reply.fragments[3].to_s)
|
92
|
+
assert_match(/inline/, reply.fragments[4].to_s)
|
93
93
|
assert_equal "\n", reply.fragments[5].to_s
|
94
94
|
assert_equal "--\nHey there, this is my signature\n", reply.fragments[6].to_s
|
95
95
|
end
|
@@ -97,9 +97,9 @@ I am currently using the Java HTTP API.\n", reply.fragments[0].to_s
|
|
97
97
|
def test_recognizes_date_string_above_quote
|
98
98
|
reply = email :email_1_4
|
99
99
|
|
100
|
-
assert_match
|
101
|
-
assert_match
|
102
|
-
assert_match
|
100
|
+
assert_match(/^Awesome/, reply.fragments[0].to_s)
|
101
|
+
assert_match(/^On/, reply.fragments[1].to_s)
|
102
|
+
assert_match(/Loader/, reply.fragments[1].to_s)
|
103
103
|
end
|
104
104
|
|
105
105
|
def test_a_complex_body_with_only_one_fragment
|
@@ -115,23 +115,28 @@ I am currently using the Java HTTP API.\n", reply.fragments[0].to_s
|
|
115
115
|
assert_equal [false, false], reply.fragments.map { |f| f.quoted? }
|
116
116
|
assert_equal [false, true], reply.fragments.map { |f| f.signature? }
|
117
117
|
assert_equal [false, true], reply.fragments.map { |f| f.hidden? }
|
118
|
-
assert_match
|
118
|
+
assert_match(/^-- \nrick/, reply.fragments[1].to_s)
|
119
119
|
end
|
120
120
|
|
121
121
|
def test_deals_with_multiline_reply_headers
|
122
122
|
reply = email :email_1_6
|
123
123
|
|
124
|
-
assert_match
|
125
|
-
assert_match
|
126
|
-
assert_match
|
124
|
+
assert_match(/^I get/, reply.fragments[0].to_s)
|
125
|
+
assert_match(/^On/, reply.fragments[1].to_s)
|
126
|
+
assert_match(/Was this/, reply.fragments[1].to_s)
|
127
127
|
end
|
128
128
|
|
129
129
|
def test_deals_with_windows_line_endings
|
130
130
|
reply = email :email_1_7
|
131
131
|
|
132
|
-
assert_match
|
133
|
-
assert_match
|
134
|
-
assert_match
|
132
|
+
assert_match(/:\+1:/, reply.fragments[0].to_s)
|
133
|
+
assert_match(/^On/, reply.fragments[1].to_s)
|
134
|
+
assert_match(/Steps 0-2/, reply.fragments[1].to_s)
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_handles_non_ascii_characters
|
138
|
+
non_ascii_body = "Here’s a test."
|
139
|
+
assert_equal non_ascii_body, EmailReplyParser.parse_reply(non_ascii_body)
|
135
140
|
end
|
136
141
|
|
137
142
|
def test_does_not_modify_input_string
|
@@ -155,6 +160,11 @@ I am currently using the Java HTTP API.\n", reply.fragments[0].to_s
|
|
155
160
|
assert_equal "Outlook with a reply directly above line", EmailReplyParser.parse_reply(body)
|
156
161
|
end
|
157
162
|
|
163
|
+
def test_parse_out_just_top_for_outlook_with_no_line
|
164
|
+
body = IO.read EMAIL_FIXTURE_PATH.join("email_2_3.txt").to_s
|
165
|
+
assert_equal "Outlook with a reply directly above line", EmailReplyParser.parse_reply(body)
|
166
|
+
end
|
167
|
+
|
158
168
|
def test_parse_out_sent_from_iPhone
|
159
169
|
body = IO.read EMAIL_FIXTURE_PATH.join("email_iPhone.txt").to_s
|
160
170
|
assert_equal "Here is another email", EmailReplyParser.parse_reply(body)
|
@@ -188,14 +198,14 @@ I am currently using the Java HTTP API.\n", reply.fragments[0].to_s
|
|
188
198
|
|
189
199
|
def test_one_is_not_on
|
190
200
|
reply = email("email_one_is_not_on")
|
191
|
-
assert_match
|
192
|
-
assert_match
|
201
|
+
assert_match(/One outstanding question/, reply.fragments[0].to_s)
|
202
|
+
assert_match(/^On Oct 1, 2012/, reply.fragments[1].to_s)
|
193
203
|
end
|
194
204
|
|
195
205
|
def test_mulitple_on
|
196
206
|
reply = email("greedy_on")
|
197
|
-
assert_match
|
198
|
-
assert_match
|
207
|
+
assert_match(/^On your remote host/, reply.fragments[0].to_s)
|
208
|
+
assert_match(/^On 9 Jan 2014/, reply.fragments[1].to_s)
|
199
209
|
assert_equal [false, true, false], reply.fragments.map { |f| f.quoted? }
|
200
210
|
assert_equal [false, false, false], reply.fragments.map { |f| f.signature? }
|
201
211
|
assert_equal [false, true, true], reply.fragments.map { |f| f.hidden? }
|
@@ -203,8 +213,8 @@ I am currently using the Java HTTP API.\n", reply.fragments[0].to_s
|
|
203
213
|
|
204
214
|
def test_pathological_emails
|
205
215
|
t0 = Time.now
|
206
|
-
|
207
|
-
assert (Time.now - t0) < 1, "Took too long, upgrade to re2 gem."
|
216
|
+
email("pathological")
|
217
|
+
assert (Time.now - t0) < 1, "Took too long, upgrade to re2 gem. See https://rubygems.org/gems/re2"
|
208
218
|
end
|
209
219
|
|
210
220
|
def test_doesnt_remove_signature_delimiter_in_mid_line
|
metadata
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: email_reply_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rick Olson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
13
|
+
description: EmailReplyParser is a small library to parse plain text email content.
|
14
|
+
This is what GitHub uses to display comments that were created from email replies.
|
14
15
|
email: technoweenie@gmail.com
|
15
16
|
executables: []
|
16
17
|
extensions: []
|
@@ -47,7 +48,8 @@ files:
|
|
47
48
|
- test/emails/greedy_on.txt
|
48
49
|
- test/emails/pathological.txt
|
49
50
|
homepage: http://github.com/github/email_reply_parser
|
50
|
-
licenses:
|
51
|
+
licenses:
|
52
|
+
- MIT
|
51
53
|
metadata: {}
|
52
54
|
post_install_message:
|
53
55
|
rdoc_options:
|
@@ -65,11 +67,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
65
67
|
- !ruby/object:Gem::Version
|
66
68
|
version: '0'
|
67
69
|
requirements: []
|
68
|
-
|
69
|
-
rubygems_version: 2.6.6
|
70
|
+
rubygems_version: 3.0.1
|
70
71
|
signing_key:
|
71
72
|
specification_version: 2
|
72
|
-
summary:
|
73
|
+
summary: EmailReplyParser is a small library to parse plain text email content.
|
73
74
|
test_files:
|
74
75
|
- test/email_reply_parser_test.rb
|
75
|
-
has_rdoc:
|