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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 18ed91d7b72ad0b331359d9719a6f69f02366bdd
4
- data.tar.gz: b97b2b17d548dfc86066001d936b49bf6035a0e1
2
+ SHA256:
3
+ metadata.gz: 1d5b9fdfe30fe4feec4e1b84c68b25180b5da4cbe6aa8cebae7d7b725c6918c6
4
+ data.tar.gz: e046ee4ce446ee8a54d2e669ae1cd10bc0ae7e5f9e55c28d439991f7c8311965
5
5
  SHA512:
6
- metadata.gz: fb73afe46d2313905f2cf542d5adf134439bed105922272f53bc6a1e93a3a786e2ab18445dcb0f6712c62251ef0a0632c8cdf1dca441b0d6b6413cd6b83cc8ba
7
- data.tar.gz: 74370b59c92a813864096e4436c8c606bdc350d1ad43af12eded545d4eea38ea76764a98c5bbb3864ef813694f51eefb3895c3622cdd78844ebfff2354be32bf
6
+ metadata.gz: 1e4680771a08970cf019ad1bbeb7a2de56b34df351cca6a6a10aaeebff681eff71e4e2fce7809667ab9e5d1505506d5835d8e180dae731825c97a1ef3ae30cf8
7
+ data.tar.gz: cef0b121c8c201116348fa880274191b1020ed189c11b0c49a8f13e5d00b619a40aeac8eafe1fb09e908e9ff179d3b47692212364192fe3d7adde33a2c6cfc5f
data/README.md CHANGED
@@ -11,7 +11,7 @@ See the [Ruby docs][rubydocs] for more information.
11
11
 
12
12
  [rubydocs]: http://rubydoc.info/gems/email_reply_parser/
13
13
 
14
- ##Usage
14
+ ## Usage
15
15
 
16
16
  To parse reply body:
17
17
 
@@ -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
- ## Make sure your summary is short. The description may be as long
24
- ## as you like.
25
- s.summary = "Short description used in Gem listings."
26
- s.description = "Long description. Maybe copied from the README."
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
-
@@ -30,7 +30,7 @@ require 'strscan'
30
30
  #
31
31
  # [mail]: https://github.com/mikel/mail
32
32
  class EmailReplyParser
33
- VERSION = "0.5.9"
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*){1,3} ym morf tneS$)'
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 /^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
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 /^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
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 /^On [^\:]+\:/, reply.fragments[0].to_s
89
- assert_match /^I will reply/, reply.fragments[1].to_s
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 /^and under this./, reply.fragments[3].to_s
92
- assert_match /inline/, reply.fragments[4].to_s
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 /^Awesome/, reply.fragments[0].to_s
101
- assert_match /^On/, reply.fragments[1].to_s
102
- assert_match /Loader/, reply.fragments[1].to_s
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 /^-- \nrick/, reply.fragments[1].to_s
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 /^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
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 /:\+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
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 /One outstanding question/, reply.fragments[0].to_s
192
- assert_match /^On Oct 1, 2012/, reply.fragments[1].to_s
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 /^On your remote host/, reply.fragments[0].to_s
198
- assert_match /^On 9 Jan 2014/, reply.fragments[1].to_s
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
- reply = email("pathological")
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.9
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: 2016-07-21 00:00:00.000000000 Z
11
+ date: 2019-08-07 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Long description. Maybe copied from the README.
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
- rubyforge_project: email_reply_parser
69
- rubygems_version: 2.6.6
70
+ rubygems_version: 3.0.1
70
71
  signing_key:
71
72
  specification_version: 2
72
- summary: Short description used in Gem listings.
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: