Skip to content

Commit

Permalink
Merge pull request #21 from deltachat/fix-email-ate-last-dot
Browse files Browse the repository at this point in the history
fix: do not parse last dot for email addresses
  • Loading branch information
Simon-Laux authored May 9, 2022
2 parents 198894d + 36877a8 commit ad4dc55
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 2 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

## Unreleased

## Changed

- update rust toolchain to `1.60.0`
- enable more clippy lints to prevent panics

## Fixed

- fix: do not parse last dot for email addresses #19

## 0.3.0 - Squashing Link Bugs

## Changed
Expand Down
27 changes: 25 additions & 2 deletions src/parser/parse_from_text/text_elements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ fn hashtag(input: &str) -> IResult<&str, Element, CustomError<&str>> {
}

fn not_email_address_part_char(c: char) -> bool {
matches!(c, '@' | '\n' | '\r' | '\t' | ' ' | ':')
matches!(
c,
'@' | '\n' | '\r' | '\t' | ' ' | ':' | ';' | '!' | '?' | ','
)
}

fn email_address_part_char(c: char) -> bool {
Expand All @@ -50,7 +53,27 @@ fn email_intern(input: &str) -> IResult<&str, (), CustomError<&str>> {
}

fn email_address(input: &str) -> IResult<&str, Element, CustomError<&str>> {
let (input, content) = recognize(email_intern)(input)?;
// basically
// let (input, content) = recognize(email_intern)(input)?;
// but don't eat the last char if it is a dot.
let i = <&str>::clone(&input);
let i2 = <&str>::clone(&input);
let i3 = <&str>::clone(&input);
let (input, content) = match email_intern(i) {
Ok((remaining, _)) => {
let index = i2.offset(remaining);
let consumed = i2.slice(..index);
if let Some('.') = consumed.chars().last() {
let index = input.offset(remaining).saturating_sub(1);
let consumed = i3.slice(..index);
let remaining = input.slice(index..);
Ok((remaining, consumed))
} else {
Ok((remaining, consumed))
}
}
Err(e) => Err(e),
}?;
// check if result is valid email
if true {
Ok((input, Element::EmailAddress(content)))
Expand Down
56 changes: 56 additions & 0 deletions tests/text_to_ast/text_only.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,62 @@ fn email_address_example() {
);
}

#[test]
fn email_address_do_not_parse_last_dot() {
assert_eq!(
parse_only_text("you can reach me on [email protected]."),
vec![
Text("you can reach me on "),
EmailAddress("[email protected]"),
Text(".")
]
);
}

#[test]
fn email_address_do_not_parse_last_char_if_special() {
assert_eq!(
parse_only_text("you can reach me on [email protected]!"),
vec![
Text("you can reach me on "),
EmailAddress("[email protected]"),
Text("!")
]
);
assert_eq!(
parse_only_text("you can reach me on [email protected]?"),
vec![
Text("you can reach me on "),
EmailAddress("[email protected]"),
Text("?")
]
);
assert_eq!(
parse_only_text("you can reach me on [email protected],"),
vec![
Text("you can reach me on "),
EmailAddress("[email protected]"),
Text(",")
]
);
assert_eq!(
parse_only_text("you can reach me on [email protected]:"),
vec![
Text("you can reach me on "),
EmailAddress("[email protected]"),
Text(":")
]
);
assert_eq!(
parse_only_text("you can reach me on [email protected];"),
vec![
Text("you can reach me on "),
EmailAddress("[email protected]"),
Text(";")
]
);
}

#[test]
fn link() {
let test_cases = vec![
Expand Down

0 comments on commit ad4dc55

Please sign in to comment.