mirror of
https://github.com/chatmail/core.git
synced 2026-04-28 10:56:29 +03:00
Display a quote if top posting is detected
Previously quote at the end was always displayed as [...].
This commit is contained in:
committed by
link2xt
parent
fa7b6c001e
commit
11d9fcad35
@@ -2268,4 +2268,35 @@ From: alice <alice@example.org>
|
||||
);
|
||||
assert_eq!(message.parts[0].msg, "");
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
async fn parse_quote_top_posting() {
|
||||
let context = TestContext::new().await;
|
||||
let raw = br##"Content-Type: text/plain; charset=utf-8; format=flowed; delsp=no
|
||||
Subject: Re: top posting
|
||||
MIME-Version: 1.0
|
||||
In-Reply-To: <bar@example.org>
|
||||
Message-ID: <foo@example.org>
|
||||
To: bob <bob@example.org>
|
||||
From: alice <alice@example.org>
|
||||
|
||||
A reply.
|
||||
|
||||
On 2020-10-25, Bob wrote:
|
||||
> A quote.
|
||||
"##;
|
||||
|
||||
let message = MimeMessage::from_bytes(&context.ctx, &raw[..])
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(message.get_subject(), Some("Re: top posting".to_string()));
|
||||
|
||||
assert_eq!(message.parts.len(), 1);
|
||||
assert_eq!(message.parts[0].typ, Viewtype::Text);
|
||||
assert_eq!(
|
||||
message.parts[0].param.get(Param::Quote).unwrap(),
|
||||
"A quote."
|
||||
);
|
||||
assert_eq!(message.parts[0].msg, "A reply.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ pub fn simplify(mut input: String, is_chat_message: bool) -> (String, bool, Opti
|
||||
let lines = split_lines(&input);
|
||||
let (lines, is_forwarded) = skip_forward_header(&lines);
|
||||
|
||||
let (lines, top_quote) = remove_top_quote(lines);
|
||||
let (lines, mut top_quote) = remove_top_quote(lines);
|
||||
let original_lines = &lines;
|
||||
let lines = remove_message_footer(lines);
|
||||
|
||||
@@ -79,12 +79,16 @@ pub fn simplify(mut input: String, is_chat_message: bool) -> (String, bool, Opti
|
||||
render_message(lines, false)
|
||||
} else {
|
||||
let (lines, has_nonstandard_footer) = remove_nonstandard_footer(lines);
|
||||
let (lines, has_bottom_quote) = remove_bottom_quote(lines);
|
||||
let (lines, mut bottom_quote) = remove_bottom_quote(lines);
|
||||
|
||||
if top_quote.is_none() && bottom_quote.is_some() {
|
||||
std::mem::swap(&mut top_quote, &mut bottom_quote);
|
||||
}
|
||||
|
||||
if lines.iter().all(|it| it.trim().is_empty()) {
|
||||
render_message(original_lines, false)
|
||||
} else {
|
||||
render_message(lines, has_nonstandard_footer || has_bottom_quote)
|
||||
render_message(lines, has_nonstandard_footer || bottom_quote.is_some())
|
||||
}
|
||||
};
|
||||
(text, is_forwarded, top_quote)
|
||||
@@ -105,16 +109,27 @@ fn skip_forward_header<'a>(lines: &'a [&str]) -> (&'a [&'a str], bool) {
|
||||
}
|
||||
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
fn remove_bottom_quote<'a>(lines: &'a [&str]) -> (&'a [&'a str], bool) {
|
||||
fn remove_bottom_quote<'a>(lines: &'a [&str]) -> (&'a [&'a str], Option<String>) {
|
||||
let mut first_quoted_line = lines.len();
|
||||
let mut last_quoted_line = None;
|
||||
for (l, line) in lines.iter().enumerate().rev() {
|
||||
if is_plain_quote(line) {
|
||||
if last_quoted_line.is_none() {
|
||||
first_quoted_line = l + 1;
|
||||
}
|
||||
last_quoted_line = Some(l)
|
||||
} else if !is_empty_line(line) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if let Some(mut l_last) = last_quoted_line {
|
||||
let quoted_text = lines[l_last..first_quoted_line]
|
||||
.iter()
|
||||
.map(|s| {
|
||||
s.strip_prefix(">")
|
||||
.map_or(*s, |u| u.strip_prefix(" ").unwrap_or(u))
|
||||
})
|
||||
.join("\n");
|
||||
if l_last > 1 && is_empty_line(lines[l_last - 1]) {
|
||||
l_last -= 1
|
||||
}
|
||||
@@ -124,9 +139,9 @@ fn remove_bottom_quote<'a>(lines: &'a [&str]) -> (&'a [&'a str], bool) {
|
||||
l_last -= 1
|
||||
}
|
||||
}
|
||||
(&lines[..l_last], true)
|
||||
(&lines[..l_last], Some(quoted_text))
|
||||
} else {
|
||||
(lines, false)
|
||||
(lines, None)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user