1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- /// This provides a list of usernames or teams that were pinged in the text
- /// provided.
- ///
- /// It will appropriately skip mentions just like GitHub, i.e., mentions inside
- /// code blocks will be ignored.
- ///
- /// Note that the `@` is skipped in the final output.
- pub fn get_mentions(input: &str) -> Vec<&str> {
- let ignore_regions = crate::ignore_block::IgnoreBlocks::new(input);
- let mut mentions = Vec::new();
- for (idx, _) in input.match_indices('@') {
- if let Some(previous) = input[..idx].chars().next_back() {
- // A github username must stand apart from other text.
- //
- // Oddly enough, english letters do not work, but letters outside
- // ASCII do work as separators; for now just go with this limited
- // list.
- if let 'a'..='z' | 'A'..='Z' = previous {
- continue;
- }
- }
- let mut saw_slash = false;
- let username_end = input
- .get(idx + 1..)
- .unwrap_or_default()
- .char_indices()
- .find(|(_, terminator)| match terminator {
- // These are the valid characters inside of a GitHub
- // username
- 'a'..='z' | 'A'..='Z' | '0'..='9' | '-' | '_' => false,
- '/' if !saw_slash => {
- saw_slash = true;
- false
- }
- _ => true,
- })
- .map(|(end, _)| idx + 1 + end)
- .unwrap_or(input.len());
- let username = input.get(idx + 1..username_end).unwrap_or_default();
- if username.is_empty() {
- continue;
- }
- if ignore_regions
- .overlaps_ignore(idx..idx + username.len())
- .is_some()
- {
- continue;
- }
- mentions.push(username);
- }
- mentions
- }
- #[test]
- fn mentions_in_code_ignored() {
- assert_eq!(
- get_mentions("@rust-lang/libs `@user`"),
- vec!["rust-lang/libs"]
- );
- assert_eq!(get_mentions("@user `@user`"), vec!["user"]);
- assert_eq!(get_mentions("`@user`"), Vec::<&str>::new());
- }
- #[test]
- fn italics() {
- assert_eq!(get_mentions("*@rust-lang/libs*"), vec!["rust-lang/libs"]);
- }
- #[test]
- fn slash() {
- assert_eq!(
- get_mentions("@rust-lang/libs/@rust-lang/release"),
- vec!["rust-lang/libs", "rust-lang/release"]
- );
- }
- #[test]
- fn no_panic_lone() {
- assert_eq!(get_mentions("@ `@`"), Vec::<&str>::new());
- }
- #[test]
- fn no_email() {
- assert_eq!(get_mentions("user@example.com"), Vec::<&str>::new());
- }
|