Allow brackets around hashtags and mentions
This commit is contained in:
parent
272ee9997b
commit
ce694cb88c
2 changed files with 51 additions and 40 deletions
|
@ -10,8 +10,8 @@ use crate::models::profiles::types::DbActorProfile;
|
||||||
|
|
||||||
// See also: USERNAME_RE in models::profiles::validators
|
// See also: USERNAME_RE in models::profiles::validators
|
||||||
const MENTION_RE: &str = r"@?(?P<user>[\w\.-]+)@(?P<instance>.+)";
|
const MENTION_RE: &str = r"@?(?P<user>[\w\.-]+)@(?P<instance>.+)";
|
||||||
const MENTION_SEARCH_RE: &str = r"(?m)(?P<before>^|\s)@(?P<user>[\w\.-]+)@(?P<instance>\S+)";
|
const MENTION_SEARCH_RE: &str = r"(?m)(?P<before>^|\s|[\(])@(?P<user>[\w\.-]+)@(?P<instance>\S+)";
|
||||||
const MENTION_SEARCH_SECONDARY_RE: &str = r"^(?P<instance>[\w\.-]+\w)(?P<after>(\.|<br>|\.<br>)?)$";
|
const MENTION_SEARCH_SECONDARY_RE: &str = r"^(?P<instance>[\w\.-]+\w)(?P<after>[\.,:?\)]?(<br>)?)$";
|
||||||
|
|
||||||
/// Finds everything that looks like a mention
|
/// Finds everything that looks like a mention
|
||||||
fn find_mentions(
|
fn find_mentions(
|
||||||
|
@ -109,22 +109,24 @@ mod tests {
|
||||||
|
|
||||||
const INSTANCE_HOST: &str = "server1.com";
|
const INSTANCE_HOST: &str = "server1.com";
|
||||||
const INSTANCE_URL: &str = "https://server1.com";
|
const INSTANCE_URL: &str = "https://server1.com";
|
||||||
|
const TEXT_WITH_MENTIONS: &str = concat!(
|
||||||
|
"@user1@server1.com ",
|
||||||
|
"(@user2@server2.com boosted) ",
|
||||||
|
"@user3@server2.com.\n",
|
||||||
|
"@@invalid@server2.com ",
|
||||||
|
"@test@server3.com@nospace@server4.com ",
|
||||||
|
"@notmention email@unknown.org ",
|
||||||
|
"@user2@server2.com copy ",
|
||||||
|
"some text",
|
||||||
|
);
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_find_mentions() {
|
fn test_find_mentions() {
|
||||||
let text = concat!(
|
let results = find_mentions(INSTANCE_HOST, TEXT_WITH_MENTIONS);
|
||||||
"@user1@server1.com ",
|
|
||||||
"@user2@server2.com ",
|
|
||||||
"@@invalid@server2.com ",
|
|
||||||
"@test@server3.com@nospace@server4.com ",
|
|
||||||
"@notmention ",
|
|
||||||
"@user2@server2.com copy ",
|
|
||||||
"some text",
|
|
||||||
);
|
|
||||||
let results = find_mentions(INSTANCE_HOST, text);
|
|
||||||
assert_eq!(results, vec![
|
assert_eq!(results, vec![
|
||||||
"user1",
|
"user1",
|
||||||
"user2@server2.com",
|
"user2@server2.com",
|
||||||
|
"user3@server2.com",
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +137,7 @@ mod tests {
|
||||||
username: "user1".to_string(),
|
username: "user1".to_string(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
// Remote actor
|
// Remote actors
|
||||||
let profile_2 = DbActorProfile {
|
let profile_2 = DbActorProfile {
|
||||||
username: "user2".to_string(),
|
username: "user2".to_string(),
|
||||||
actor_json: Some(Actor {
|
actor_json: Some(Actor {
|
||||||
|
@ -145,20 +147,33 @@ mod tests {
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let text = concat!(
|
let profile_3 = DbActorProfile {
|
||||||
"@user1@server1.com @user2@server2.com.\n",
|
username: "user3".to_string(),
|
||||||
"sometext @notmention @test@unknown.org"
|
actor_json: Some(Actor {
|
||||||
);
|
id: "https://server2.com/actors/user3".to_string(),
|
||||||
|
url: Some("https://server2.com/@user3".to_string()),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
let mention_map = HashMap::from([
|
let mention_map = HashMap::from([
|
||||||
("user1".to_string(), profile_1),
|
("user1".to_string(), profile_1),
|
||||||
("user2@server2.com".to_string(), profile_2),
|
("user2@server2.com".to_string(), profile_2),
|
||||||
|
("user3@server2.com".to_string(), profile_3),
|
||||||
]);
|
]);
|
||||||
let result = replace_mentions(&mention_map, INSTANCE_HOST, INSTANCE_URL, text);
|
let result = replace_mentions(
|
||||||
|
&mention_map,
|
||||||
|
INSTANCE_HOST,
|
||||||
|
INSTANCE_URL,
|
||||||
|
TEXT_WITH_MENTIONS,
|
||||||
|
);
|
||||||
|
|
||||||
let expected_result = concat!(
|
let expected_result = concat!(
|
||||||
r#"<span class="h-card"><a class="u-url mention" href="https://server1.com/users/user1">@user1</a></span> "#,
|
r#"<span class="h-card"><a class="u-url mention" href="https://server1.com/users/user1">@user1</a></span> "#,
|
||||||
r#"<span class="h-card"><a class="u-url mention" href="https://server2.com/@user2">@user2</a></span>."#, "\n",
|
r#"(<span class="h-card"><a class="u-url mention" href="https://server2.com/@user2">@user2</a></span> boosted) "#,
|
||||||
r#"sometext @notmention @test@unknown.org"#,
|
r#"<span class="h-card"><a class="u-url mention" href="https://server2.com/@user3">@user3</a></span>."#, "\n",
|
||||||
|
r#"@@invalid@server2.com @test@server3.com@nospace@server4.com "#,
|
||||||
|
r#"@notmention email@unknown.org <span class="h-card"><a class="u-url mention" href="https://server2.com/@user2">@user2</a></span> copy some text"#,
|
||||||
);
|
);
|
||||||
assert_eq!(result, expected_result);
|
assert_eq!(result, expected_result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ use regex::{Captures, Regex};
|
||||||
use crate::errors::ValidationError;
|
use crate::errors::ValidationError;
|
||||||
use crate::frontend::get_tag_page_url;
|
use crate::frontend::get_tag_page_url;
|
||||||
|
|
||||||
const HASHTAG_RE: &str = r"(?m)(?P<before>^|\s)#(?P<tag>\S+)";
|
const HASHTAG_RE: &str = r"(?m)(?P<before>^|\s|[\(])#(?P<tag>\S+)";
|
||||||
const HASHTAG_SECONDARY_RE: &str = r"^(?P<tag>[0-9A-Za-z]+)(?P<after>[\.,:?]?(<br>)?)$";
|
const HASHTAG_SECONDARY_RE: &str = r"^(?P<tag>[0-9A-Za-z]+)(?P<after>[\.,:?\)]?(<br>)?)$";
|
||||||
const HASHTAG_NAME_RE: &str = r"^\w+$";
|
const HASHTAG_NAME_RE: &str = r"^\w+$";
|
||||||
|
|
||||||
/// Finds anything that looks like a hashtag
|
/// Finds anything that looks like a hashtag
|
||||||
|
@ -63,16 +63,16 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
const INSTANCE_URL: &str = "https://example.com";
|
const INSTANCE_URL: &str = "https://example.com";
|
||||||
|
const TEXT_WITH_TAGS: &str = concat!(
|
||||||
|
"@user1@server1 some text #TestTag.\n",
|
||||||
|
"#TAG1 #tag1 #test_underscore #test*special ",
|
||||||
|
"more text (#tag2) text #tag3, #tag4:<br>\n",
|
||||||
|
"end with #tag5",
|
||||||
|
);
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_find_tags() {
|
fn test_find_tags() {
|
||||||
let text = concat!(
|
let tags = find_tags(TEXT_WITH_TAGS);
|
||||||
"@user1@server1 some text #TestTag.\n",
|
|
||||||
"#TAG1 #tag1 #test_underscore #test*special ",
|
|
||||||
"more text #tag2, #tag3:<br>\n",
|
|
||||||
"end with #tag4",
|
|
||||||
);
|
|
||||||
let tags = find_tags(text);
|
|
||||||
|
|
||||||
assert_eq!(tags, vec![
|
assert_eq!(tags, vec![
|
||||||
"testtag",
|
"testtag",
|
||||||
|
@ -80,27 +80,23 @@ mod tests {
|
||||||
"tag2",
|
"tag2",
|
||||||
"tag3",
|
"tag3",
|
||||||
"tag4",
|
"tag4",
|
||||||
|
"tag5",
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_replace_tags() {
|
fn test_replace_tags() {
|
||||||
let text = concat!(
|
let tags = find_tags(TEXT_WITH_TAGS);
|
||||||
"@user1@server1 some text #TestTag.\n",
|
let output = replace_tags(INSTANCE_URL, TEXT_WITH_TAGS, &tags);
|
||||||
"#TAG1 #tag1 #test_underscore #test*special ",
|
|
||||||
"more text #tag2, #tag3:<br>\n",
|
|
||||||
"end with #tag4",
|
|
||||||
);
|
|
||||||
let tags = find_tags(text);
|
|
||||||
let output = replace_tags(INSTANCE_URL, &text, &tags);
|
|
||||||
|
|
||||||
let expected_output = concat!(
|
let expected_output = concat!(
|
||||||
r#"@user1@server1 some text <a class="hashtag" href="https://example.com/tag/testtag">#TestTag</a>."#, "\n",
|
r#"@user1@server1 some text <a class="hashtag" href="https://example.com/tag/testtag">#TestTag</a>."#, "\n",
|
||||||
r#"<a class="hashtag" href="https://example.com/tag/tag1">#TAG1</a> <a class="hashtag" href="https://example.com/tag/tag1">#tag1</a> "#,
|
r#"<a class="hashtag" href="https://example.com/tag/tag1">#TAG1</a> <a class="hashtag" href="https://example.com/tag/tag1">#tag1</a> "#,
|
||||||
r#"#test_underscore #test*special "#,
|
r#"#test_underscore #test*special "#,
|
||||||
r#"more text <a class="hashtag" href="https://example.com/tag/tag2">#tag2</a>, "#,
|
r#"more text (<a class="hashtag" href="https://example.com/tag/tag2">#tag2</a>) text "#,
|
||||||
r#"<a class="hashtag" href="https://example.com/tag/tag3">#tag3</a>:<br>"#, "\n",
|
r#"<a class="hashtag" href="https://example.com/tag/tag3">#tag3</a>, "#,
|
||||||
r#"end with <a class="hashtag" href="https://example.com/tag/tag4">#tag4</a>"#,
|
r#"<a class="hashtag" href="https://example.com/tag/tag4">#tag4</a>:<br>"#, "\n",
|
||||||
|
r#"end with <a class="hashtag" href="https://example.com/tag/tag5">#tag5</a>"#,
|
||||||
);
|
);
|
||||||
assert_eq!(output, expected_output);
|
assert_eq!(output, expected_output);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue