email_reply_trimmer 0.1.13 → 0.2.0
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/Gemfile +1 -0
- data/Gemfile.lock +98 -0
- data/README.md +4 -4
- data/Rakefile +3 -6
- data/devenv.lock +184 -0
- data/devenv.nix +4 -0
- data/devenv.yaml +8 -0
- data/email_reply_trimmer.gemspec +4 -2
- data/lib/email_reply_trimmer/delimiter_matcher.rb +3 -2
- data/lib/email_reply_trimmer/email_header_matcher.rb +6 -5
- data/lib/email_reply_trimmer/embedded_email_matcher.rb +3 -2
- data/lib/email_reply_trimmer/empty_line_matcher.rb +1 -0
- data/lib/email_reply_trimmer/quote_matcher.rb +1 -0
- data/lib/email_reply_trimmer/signature_matcher.rb +2 -1
- data/lib/email_reply_trimmer.rb +25 -4
- data/test/elided/block_code_spacers.txt +0 -0
- data/test/emails/block_code_spacers.txt +13 -0
- data/test/test_email_matcher.rb +1 -0
- data/test/test_email_reply_trimmer.rb +1 -0
- data/test/trimmed/block_code_spacers.txt +13 -0
- metadata +32 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9914eb793e4bbfa4f291097707acb2af27f491507b0e52b0e1433df3c1fb1f0d
|
4
|
+
data.tar.gz: 2c519cd4b6fe2db1dc3b12201c8a5bd540fbf274537610069b73d34bb3e0566f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0687f10183b5472c816d433c3f654dd085b8d615ef223c54e97e61e893c47752ed20eb5b1354c7d184ab84075de3c3fa492c76191b1fc0cfdcfc48a1d661b34
|
7
|
+
data.tar.gz: 3d740b872f6116bd0c59d2d1b19e405191f1c25c619e5564a602eebed3691323761292d7a063f7f224bacd668f2ede622eac085f7a5b7bad3b90570ac3b018b9
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
email_reply_trimmer (0.2.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
activesupport (8.0.0)
|
10
|
+
base64
|
11
|
+
benchmark (>= 0.3)
|
12
|
+
bigdecimal
|
13
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
14
|
+
connection_pool (>= 2.2.5)
|
15
|
+
drb
|
16
|
+
i18n (>= 1.6, < 2)
|
17
|
+
logger (>= 1.4.2)
|
18
|
+
minitest (>= 5.1)
|
19
|
+
securerandom (>= 0.3)
|
20
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
21
|
+
uri (>= 0.13.1)
|
22
|
+
ast (2.4.2)
|
23
|
+
base64 (0.2.0)
|
24
|
+
benchmark (0.4.0)
|
25
|
+
bigdecimal (3.1.8)
|
26
|
+
concurrent-ruby (1.3.4)
|
27
|
+
connection_pool (2.4.1)
|
28
|
+
drb (2.2.1)
|
29
|
+
i18n (1.14.6)
|
30
|
+
concurrent-ruby (~> 1.0)
|
31
|
+
json (2.8.2)
|
32
|
+
language_server-protocol (3.17.0.3)
|
33
|
+
logger (1.6.1)
|
34
|
+
minitest (5.25.2)
|
35
|
+
parallel (1.26.3)
|
36
|
+
parser (3.3.6.0)
|
37
|
+
ast (~> 2.4.1)
|
38
|
+
racc
|
39
|
+
racc (1.8.1)
|
40
|
+
rack (3.1.8)
|
41
|
+
rainbow (3.1.1)
|
42
|
+
rake (12.3.3)
|
43
|
+
regexp_parser (2.9.2)
|
44
|
+
rubocop (1.69.0)
|
45
|
+
json (~> 2.3)
|
46
|
+
language_server-protocol (>= 3.17.0)
|
47
|
+
parallel (~> 1.10)
|
48
|
+
parser (>= 3.3.0.2)
|
49
|
+
rainbow (>= 2.2.2, < 4.0)
|
50
|
+
regexp_parser (>= 2.4, < 3.0)
|
51
|
+
rubocop-ast (>= 1.36.1, < 2.0)
|
52
|
+
ruby-progressbar (~> 1.7)
|
53
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
54
|
+
rubocop-ast (1.36.2)
|
55
|
+
parser (>= 3.3.1.0)
|
56
|
+
rubocop-capybara (2.21.0)
|
57
|
+
rubocop (~> 1.41)
|
58
|
+
rubocop-discourse (3.8.6)
|
59
|
+
activesupport (>= 6.1)
|
60
|
+
rubocop (>= 1.59.0)
|
61
|
+
rubocop-capybara (>= 2.0.0)
|
62
|
+
rubocop-factory_bot (>= 2.0.0)
|
63
|
+
rubocop-rails (>= 2.25.0)
|
64
|
+
rubocop-rspec (>= 3.0.1)
|
65
|
+
rubocop-rspec_rails (>= 2.30.0)
|
66
|
+
rubocop-factory_bot (2.26.1)
|
67
|
+
rubocop (~> 1.61)
|
68
|
+
rubocop-rails (2.27.0)
|
69
|
+
activesupport (>= 4.2.0)
|
70
|
+
rack (>= 1.1)
|
71
|
+
rubocop (>= 1.52.0, < 2.0)
|
72
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
73
|
+
rubocop-rspec (3.2.0)
|
74
|
+
rubocop (~> 1.61)
|
75
|
+
rubocop-rspec_rails (2.30.0)
|
76
|
+
rubocop (~> 1.61)
|
77
|
+
rubocop-rspec (~> 3, >= 3.0.1)
|
78
|
+
ruby-progressbar (1.13.0)
|
79
|
+
securerandom (0.3.2)
|
80
|
+
tzinfo (2.0.6)
|
81
|
+
concurrent-ruby (~> 1.0)
|
82
|
+
unicode-display_width (3.1.2)
|
83
|
+
unicode-emoji (~> 4.0, >= 4.0.4)
|
84
|
+
unicode-emoji (4.0.4)
|
85
|
+
uri (1.0.2)
|
86
|
+
|
87
|
+
PLATFORMS
|
88
|
+
ruby
|
89
|
+
|
90
|
+
DEPENDENCIES
|
91
|
+
email_reply_trimmer!
|
92
|
+
minitest (~> 5)
|
93
|
+
rake (~> 12)
|
94
|
+
rubocop
|
95
|
+
rubocop-discourse
|
96
|
+
|
97
|
+
BUNDLED WITH
|
98
|
+
2.5.22
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Discourse Email Reply Trimmer
|
1
|
+
# Discourse Email Reply Trimmer
|
2
2
|
|
3
3
|
EmailReplyTrimmer is a small library to trim replies from plain text email.
|
4
4
|
|
@@ -16,6 +16,6 @@ Run `rake` to run the tests.
|
|
16
16
|
|
17
17
|
## Inspirations
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
- [GitHub's Email Reply Parser](https://github.com/github/email_reply_parser)
|
20
|
+
- [MailGun's Talon](https://github.com/mailgun/talon)
|
21
|
+
- [Vitor R. Carvalho's Learning to Extract Signature and Reply Lines from Email](http://www.cs.cmu.edu/~vitor/papers/sigFilePaper_finalversion.pdf)
|
data/Rakefile
CHANGED
@@ -1,10 +1,7 @@
|
|
1
|
-
|
2
|
-
@name ||= Dir["*.gemspec"].first.split(".").first
|
3
|
-
end
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
end
|
3
|
+
name = Dir["*.gemspec"].first.split(".").first
|
4
|
+
version = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*['"](?'version'\d+\.\d+\.\d+)['"]/, "version"]
|
8
5
|
|
9
6
|
task default: :test
|
10
7
|
|
data/devenv.lock
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
{
|
2
|
+
"nodes": {
|
3
|
+
"devenv": {
|
4
|
+
"locked": {
|
5
|
+
"dir": "src/modules",
|
6
|
+
"lastModified": 1732830318,
|
7
|
+
"owner": "cachix",
|
8
|
+
"repo": "devenv",
|
9
|
+
"rev": "51abcb75d471a215c800937d4e30dc765d305c6d",
|
10
|
+
"type": "github"
|
11
|
+
},
|
12
|
+
"original": {
|
13
|
+
"dir": "src/modules",
|
14
|
+
"owner": "cachix",
|
15
|
+
"repo": "devenv",
|
16
|
+
"type": "github"
|
17
|
+
}
|
18
|
+
},
|
19
|
+
"flake-compat": {
|
20
|
+
"flake": false,
|
21
|
+
"locked": {
|
22
|
+
"lastModified": 1732722421,
|
23
|
+
"owner": "edolstra",
|
24
|
+
"repo": "flake-compat",
|
25
|
+
"rev": "9ed2ac151eada2306ca8c418ebd97807bb08f6ac",
|
26
|
+
"type": "github"
|
27
|
+
},
|
28
|
+
"original": {
|
29
|
+
"owner": "edolstra",
|
30
|
+
"repo": "flake-compat",
|
31
|
+
"type": "github"
|
32
|
+
}
|
33
|
+
},
|
34
|
+
"flake-compat_2": {
|
35
|
+
"flake": false,
|
36
|
+
"locked": {
|
37
|
+
"lastModified": 1732722421,
|
38
|
+
"owner": "edolstra",
|
39
|
+
"repo": "flake-compat",
|
40
|
+
"rev": "9ed2ac151eada2306ca8c418ebd97807bb08f6ac",
|
41
|
+
"type": "github"
|
42
|
+
},
|
43
|
+
"original": {
|
44
|
+
"owner": "edolstra",
|
45
|
+
"repo": "flake-compat",
|
46
|
+
"type": "github"
|
47
|
+
}
|
48
|
+
},
|
49
|
+
"flake-utils": {
|
50
|
+
"inputs": {
|
51
|
+
"systems": "systems"
|
52
|
+
},
|
53
|
+
"locked": {
|
54
|
+
"lastModified": 1731533236,
|
55
|
+
"owner": "numtide",
|
56
|
+
"repo": "flake-utils",
|
57
|
+
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
58
|
+
"type": "github"
|
59
|
+
},
|
60
|
+
"original": {
|
61
|
+
"owner": "numtide",
|
62
|
+
"repo": "flake-utils",
|
63
|
+
"type": "github"
|
64
|
+
}
|
65
|
+
},
|
66
|
+
"gitignore": {
|
67
|
+
"inputs": {
|
68
|
+
"nixpkgs": [
|
69
|
+
"pre-commit-hooks",
|
70
|
+
"nixpkgs"
|
71
|
+
]
|
72
|
+
},
|
73
|
+
"locked": {
|
74
|
+
"lastModified": 1709087332,
|
75
|
+
"owner": "hercules-ci",
|
76
|
+
"repo": "gitignore.nix",
|
77
|
+
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
78
|
+
"type": "github"
|
79
|
+
},
|
80
|
+
"original": {
|
81
|
+
"owner": "hercules-ci",
|
82
|
+
"repo": "gitignore.nix",
|
83
|
+
"type": "github"
|
84
|
+
}
|
85
|
+
},
|
86
|
+
"nixpkgs": {
|
87
|
+
"locked": {
|
88
|
+
"lastModified": 1732617236,
|
89
|
+
"owner": "nixos",
|
90
|
+
"repo": "nixpkgs",
|
91
|
+
"rev": "af51545ec9a44eadf3fe3547610a5cdd882bc34e",
|
92
|
+
"type": "github"
|
93
|
+
},
|
94
|
+
"original": {
|
95
|
+
"owner": "nixos",
|
96
|
+
"ref": "nixpkgs-unstable",
|
97
|
+
"repo": "nixpkgs",
|
98
|
+
"type": "github"
|
99
|
+
}
|
100
|
+
},
|
101
|
+
"nixpkgs-ruby": {
|
102
|
+
"inputs": {
|
103
|
+
"flake-compat": "flake-compat",
|
104
|
+
"flake-utils": "flake-utils",
|
105
|
+
"nixpkgs": [
|
106
|
+
"nixpkgs"
|
107
|
+
]
|
108
|
+
},
|
109
|
+
"locked": {
|
110
|
+
"lastModified": 1730958464,
|
111
|
+
"owner": "bobvanderlinden",
|
112
|
+
"repo": "nixpkgs-ruby",
|
113
|
+
"rev": "93bd040be2856ba0e44a33db6360e8c9c0c09aa1",
|
114
|
+
"type": "github"
|
115
|
+
},
|
116
|
+
"original": {
|
117
|
+
"owner": "bobvanderlinden",
|
118
|
+
"repo": "nixpkgs-ruby",
|
119
|
+
"type": "github"
|
120
|
+
}
|
121
|
+
},
|
122
|
+
"nixpkgs-stable": {
|
123
|
+
"locked": {
|
124
|
+
"lastModified": 1732749044,
|
125
|
+
"owner": "NixOS",
|
126
|
+
"repo": "nixpkgs",
|
127
|
+
"rev": "0c5b4ecbed5b155b705336aa96d878e55acd8685",
|
128
|
+
"type": "github"
|
129
|
+
},
|
130
|
+
"original": {
|
131
|
+
"owner": "NixOS",
|
132
|
+
"ref": "nixos-24.05",
|
133
|
+
"repo": "nixpkgs",
|
134
|
+
"type": "github"
|
135
|
+
}
|
136
|
+
},
|
137
|
+
"pre-commit-hooks": {
|
138
|
+
"inputs": {
|
139
|
+
"flake-compat": "flake-compat_2",
|
140
|
+
"gitignore": "gitignore",
|
141
|
+
"nixpkgs": [
|
142
|
+
"nixpkgs"
|
143
|
+
],
|
144
|
+
"nixpkgs-stable": "nixpkgs-stable"
|
145
|
+
},
|
146
|
+
"locked": {
|
147
|
+
"lastModified": 1732021966,
|
148
|
+
"owner": "cachix",
|
149
|
+
"repo": "pre-commit-hooks.nix",
|
150
|
+
"rev": "3308484d1a443fc5bc92012435d79e80458fe43c",
|
151
|
+
"type": "github"
|
152
|
+
},
|
153
|
+
"original": {
|
154
|
+
"owner": "cachix",
|
155
|
+
"repo": "pre-commit-hooks.nix",
|
156
|
+
"type": "github"
|
157
|
+
}
|
158
|
+
},
|
159
|
+
"root": {
|
160
|
+
"inputs": {
|
161
|
+
"devenv": "devenv",
|
162
|
+
"nixpkgs": "nixpkgs",
|
163
|
+
"nixpkgs-ruby": "nixpkgs-ruby",
|
164
|
+
"pre-commit-hooks": "pre-commit-hooks"
|
165
|
+
}
|
166
|
+
},
|
167
|
+
"systems": {
|
168
|
+
"locked": {
|
169
|
+
"lastModified": 1681028828,
|
170
|
+
"owner": "nix-systems",
|
171
|
+
"repo": "default",
|
172
|
+
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
173
|
+
"type": "github"
|
174
|
+
},
|
175
|
+
"original": {
|
176
|
+
"owner": "nix-systems",
|
177
|
+
"repo": "default",
|
178
|
+
"type": "github"
|
179
|
+
}
|
180
|
+
}
|
181
|
+
},
|
182
|
+
"root": "root",
|
183
|
+
"version": 7
|
184
|
+
}
|
data/devenv.nix
ADDED
data/devenv.yaml
ADDED
data/email_reply_trimmer.gemspec
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require_relative "lib/email_reply_trimmer"
|
2
3
|
|
3
4
|
Gem::Specification.new do |s|
|
@@ -9,7 +10,7 @@ Gem::Specification.new do |s|
|
|
9
10
|
s.description = "EmailReplyTrimmer is a small library to trim replies from plain text email."
|
10
11
|
|
11
12
|
s.authors = ["Régis Hanol"]
|
12
|
-
s.email = ["
|
13
|
+
s.email = ["rubygems@hanol.fr"]
|
13
14
|
|
14
15
|
s.homepage = "https://github.com/discourse/email_reply_trimmer"
|
15
16
|
s.license = "MIT"
|
@@ -20,5 +21,6 @@ Gem::Specification.new do |s|
|
|
20
21
|
|
21
22
|
s.add_development_dependency 'rake', '~> 12'
|
22
23
|
s.add_development_dependency 'minitest', '~> 5'
|
23
|
-
s.add_development_dependency 'rubocop'
|
24
|
+
s.add_development_dependency 'rubocop'
|
25
|
+
s.add_development_dependency 'rubocop-discourse'
|
24
26
|
end
|
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
class DelimiterMatcher
|
2
3
|
|
3
|
-
DELIMITER_CHARACTERS
|
4
|
-
DELIMITER_REGEX
|
4
|
+
DELIMITER_CHARACTERS = "-_,=+~#*ᐧ—"
|
5
|
+
DELIMITER_REGEX = /^[[:blank:]]*[#{Regexp.escape(DELIMITER_CHARACTERS)}]+[[:blank:]]*$/
|
5
6
|
|
6
7
|
def self.match?(line)
|
7
8
|
line =~ DELIMITER_REGEX
|
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
class EmailHeaderMatcher
|
2
3
|
|
3
|
-
EMAIL_HEADERS_WITH_DATE_MARKERS
|
4
|
+
EMAIL_HEADERS_WITH_DATE_MARKERS = [
|
4
5
|
# Norwegian
|
5
6
|
["Sendt"],
|
6
7
|
# English
|
@@ -25,11 +26,11 @@ class EmailHeaderMatcher
|
|
25
26
|
["发送时间"],
|
26
27
|
]
|
27
28
|
|
28
|
-
EMAIL_HEADERS_WITH_DATE_REGEXES
|
29
|
+
EMAIL_HEADERS_WITH_DATE_REGEXES = EMAIL_HEADERS_WITH_DATE_MARKERS.map do |header|
|
29
30
|
/^[[:blank:]*]*(?:#{header.join("|")})[[:blank:]*]*:.*\d+/
|
30
31
|
end
|
31
32
|
|
32
|
-
EMAIL_HEADERS_WITH_TEXT_MARKERS
|
33
|
+
EMAIL_HEADERS_WITH_TEXT_MARKERS = [
|
33
34
|
# Norwegian
|
34
35
|
["Fra", "Til", "Emne"],
|
35
36
|
# English
|
@@ -52,11 +53,11 @@ class EmailHeaderMatcher
|
|
52
53
|
["发件人", "收件人", "主题"],
|
53
54
|
]
|
54
55
|
|
55
|
-
EMAIL_HEADERS_WITH_TEXT_REGEXES
|
56
|
+
EMAIL_HEADERS_WITH_TEXT_REGEXES = EMAIL_HEADERS_WITH_TEXT_MARKERS.map do |header|
|
56
57
|
/^[[:blank:]*]*(?:#{header.join("|")})[[:blank:]*]*:.*[[:word:]]+/i
|
57
58
|
end
|
58
59
|
|
59
|
-
EMAIL_HEADER_REGEXES
|
60
|
+
EMAIL_HEADER_REGEXES = [
|
60
61
|
EMAIL_HEADERS_WITH_DATE_REGEXES,
|
61
62
|
EMAIL_HEADERS_WITH_TEXT_REGEXES,
|
62
63
|
].flatten
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
class EmbeddedEmailMatcher
|
2
3
|
|
3
4
|
# On Wed, Sep 25, 2013, at 03:57 PM, jorge_castro wrote:
|
@@ -11,7 +12,7 @@ class EmbeddedEmailMatcher
|
|
11
12
|
# Em seg, 27 de jul de 2015 17:13, Neil Lalonde <info@discourse.org> escreveu:
|
12
13
|
# El jueves, 21 de noviembre de 2013, codinghorror escribió:
|
13
14
|
# At 6/16/2016 08:32 PM, you wrote:
|
14
|
-
ON_DATE_SOMEONE_WROTE_REGEXES
|
15
|
+
ON_DATE_SOMEONE_WROTE_REGEXES = [
|
15
16
|
# Chinese
|
16
17
|
/^[[:blank:]<>-]*在 (?:(?!\b(?>在|写道)\b).)+?写道[[:blank:].:>-]*$/im,
|
17
18
|
# Dutch
|
@@ -72,7 +73,7 @@ class EmbeddedEmailMatcher
|
|
72
73
|
end
|
73
74
|
|
74
75
|
# Max Mustermann <try_discourse@discoursemail.com> schrieb am Fr., 28. Apr. 2017 um 11:53 Uhr:
|
75
|
-
SOMEONE_WROTE_ON_DATE_REGEXES
|
76
|
+
SOMEONE_WROTE_ON_DATE_REGEXES = [
|
76
77
|
# English
|
77
78
|
/^.+\bwrote\b[[:space:]]+\bon\b.+[^:]+:/,
|
78
79
|
# German
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
class SignatureMatcher
|
2
3
|
|
3
4
|
# Envoyé depuis mon iPhone
|
@@ -13,7 +14,7 @@ class SignatureMatcher
|
|
13
14
|
# (sent from a phone)
|
14
15
|
# (Sent from mobile device)
|
15
16
|
# 從我的 iPhone 傳送
|
16
|
-
SIGNATURE_REGEXES
|
17
|
+
SIGNATURE_REGEXES = [
|
17
18
|
# Chinese
|
18
19
|
/^[[:blank:]]*從我的 iPhone 傳送/i,
|
19
20
|
# English
|
data/lib/email_reply_trimmer.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require_relative "email_reply_trimmer/empty_line_matcher"
|
2
3
|
require_relative "email_reply_trimmer/delimiter_matcher"
|
3
4
|
require_relative "email_reply_trimmer/signature_matcher"
|
4
5
|
require_relative "email_reply_trimmer/embedded_email_matcher"
|
5
6
|
require_relative "email_reply_trimmer/email_header_matcher"
|
6
7
|
require_relative "email_reply_trimmer/quote_matcher"
|
8
|
+
require 'securerandom'
|
7
9
|
|
8
10
|
class EmailReplyTrimmer
|
9
|
-
VERSION = "0.
|
11
|
+
VERSION = "0.2.0"
|
10
12
|
|
11
13
|
DELIMITER = "d"
|
12
14
|
EMBEDDED = "b"
|
@@ -23,7 +25,7 @@ class EmailReplyTrimmer
|
|
23
25
|
return EMBEDDED if EmbeddedEmailMatcher.match? line
|
24
26
|
return EMAIL_HEADER if EmailHeaderMatcher.match? line
|
25
27
|
return QUOTE if QuoteMatcher.match? line
|
26
|
-
|
28
|
+
TEXT
|
27
29
|
end
|
28
30
|
|
29
31
|
def self.trim(text, split = false)
|
@@ -32,11 +34,14 @@ class EmailReplyTrimmer
|
|
32
34
|
# do some cleanup
|
33
35
|
preprocess!(text)
|
34
36
|
|
37
|
+
# stash the code blocks - replace them with hashes
|
38
|
+
text, blocks = hoist_code_blocks(text)
|
39
|
+
|
35
40
|
# from now on, we'll work on a line-by-line basis
|
36
41
|
lines = text.split("\n")
|
37
42
|
lines_dup = lines.dup
|
38
43
|
|
39
|
-
#
|
44
|
+
# create a string of characters, one per line, according to the line content
|
40
45
|
pattern = lines.map { |l| identify_line_content(l) }.join
|
41
46
|
|
42
47
|
# remove everything after the first delimiter
|
@@ -123,6 +128,9 @@ class EmailReplyTrimmer
|
|
123
128
|
# results
|
124
129
|
trimmed = lines.join("\n").strip
|
125
130
|
|
131
|
+
# re-inject code blocks
|
132
|
+
blocks.each { |token, block| trimmed.gsub!(token, block) }
|
133
|
+
|
126
134
|
if split
|
127
135
|
[trimmed, compute_elided(lines_dup, lines)]
|
128
136
|
else
|
@@ -151,12 +159,25 @@ class EmailReplyTrimmer
|
|
151
159
|
|
152
160
|
if index
|
153
161
|
before = lines[0...(pattern[0...index] =~ /e*(b[eqd]*|b*[ed]*)$/)].join("\n").strip
|
154
|
-
|
162
|
+
[embedded, before]
|
155
163
|
end
|
156
164
|
end
|
157
165
|
|
158
166
|
private
|
159
167
|
|
168
|
+
def self.hoist_code_blocks(text)
|
169
|
+
blocks = {}
|
170
|
+
pattern = /^```\w*$\n.*?^```$/m
|
171
|
+
|
172
|
+
text.gsub!(pattern) do |block|
|
173
|
+
token = SecureRandom.hex
|
174
|
+
blocks[token] = block
|
175
|
+
token
|
176
|
+
end
|
177
|
+
|
178
|
+
[text, blocks]
|
179
|
+
end
|
180
|
+
|
160
181
|
def self.preprocess!(text)
|
161
182
|
# normalize line endings
|
162
183
|
text.gsub!("\r\n", "\n")
|
File without changes
|
data/test/test_email_matcher.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: email_reply_trimmer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Régis Hanol
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-11-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -42,28 +42,46 @@ dependencies:
|
|
42
42
|
name: rubocop
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop-discourse
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0
|
68
|
+
version: '0'
|
55
69
|
description: EmailReplyTrimmer is a small library to trim replies from plain text
|
56
70
|
email.
|
57
71
|
email:
|
58
|
-
-
|
72
|
+
- rubygems@hanol.fr
|
59
73
|
executables: []
|
60
74
|
extensions: []
|
61
75
|
extra_rdoc_files: []
|
62
76
|
files:
|
63
77
|
- Gemfile
|
78
|
+
- Gemfile.lock
|
64
79
|
- LICENSE
|
65
80
|
- README.md
|
66
81
|
- Rakefile
|
82
|
+
- devenv.lock
|
83
|
+
- devenv.nix
|
84
|
+
- devenv.yaml
|
67
85
|
- email_reply_trimmer.gemspec
|
68
86
|
- lib/email_reply_trimmer.rb
|
69
87
|
- lib/email_reply_trimmer/delimiter_matcher.rb
|
@@ -82,6 +100,7 @@ files:
|
|
82
100
|
- test/before/forwarded_apple.txt
|
83
101
|
- test/before/forwarded_gmail.txt
|
84
102
|
- test/before/forwarded_message.txt
|
103
|
+
- test/elided/block_code_spacers.txt
|
85
104
|
- test/elided/delimiters.txt
|
86
105
|
- test/elided/dual_embedded.txt
|
87
106
|
- test/elided/email_headers_1.txt
|
@@ -145,6 +164,7 @@ files:
|
|
145
164
|
- test/elided/strip.txt
|
146
165
|
- test/elided/text_only.txt
|
147
166
|
- test/elided/usenet.txt
|
167
|
+
- test/emails/block_code_spacers.txt
|
148
168
|
- test/emails/delimiters.txt
|
149
169
|
- test/emails/dual_embedded.txt
|
150
170
|
- test/emails/email_headers_1.txt
|
@@ -221,6 +241,7 @@ files:
|
|
221
241
|
- test/matchers/does_not_contain_embedded_email.txt
|
222
242
|
- test/test_email_matcher.rb
|
223
243
|
- test/test_email_reply_trimmer.rb
|
244
|
+
- test/trimmed/block_code_spacers.txt
|
224
245
|
- test/trimmed/delimiters.txt
|
225
246
|
- test/trimmed/dual_embedded.txt
|
226
247
|
- test/trimmed/email_headers_1.txt
|
@@ -288,7 +309,7 @@ homepage: https://github.com/discourse/email_reply_trimmer
|
|
288
309
|
licenses:
|
289
310
|
- MIT
|
290
311
|
metadata: {}
|
291
|
-
post_install_message:
|
312
|
+
post_install_message:
|
292
313
|
rdoc_options: []
|
293
314
|
require_paths:
|
294
315
|
- lib
|
@@ -303,8 +324,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
303
324
|
- !ruby/object:Gem::Version
|
304
325
|
version: '0'
|
305
326
|
requirements: []
|
306
|
-
rubygems_version: 3.
|
307
|
-
signing_key:
|
327
|
+
rubygems_version: 3.4.19
|
328
|
+
signing_key:
|
308
329
|
specification_version: 4
|
309
330
|
summary: Library to trim replies from plain text email.
|
310
331
|
test_files: []
|