|
1 | 1 | pub mod logging;
|
| 2 | +pub mod text; |
2 | 3 | pub mod timing;
|
3 |
| - |
4 |
| -/// Converts GitHub @mentions to markdown-backticked text to prevent notifications. |
5 |
| -/// For example, "@user" becomes "`user`". |
6 |
| -/// |
7 |
| -/// Handles GitHub mention formats: |
8 |
| -/// - Usernames (@username) |
9 |
| -/// - Teams (@org/team) |
10 |
| -/// - Nested teams (@org/team/subteam) |
11 |
| -/// |
12 |
| -/// GitHub's nested team documentation: |
13 |
| -/// https://docs.github.com/en/organizations/organizing-members-into-teams/about-teams#nested-teams |
14 |
| -/// |
15 |
| -/// Ignores email addresses and other @ symbols that don't match GitHub mention patterns. |
16 |
| -pub fn suppress_github_mentions(text: &str) -> String { |
17 |
| - if text.is_empty() || !text.contains('@') { |
18 |
| - return text.to_string(); |
19 |
| - } |
20 |
| - |
21 |
| - let segment = r"[A-Za-z0-9][A-Za-z0-9\-]{0,38}"; |
22 |
| - let pattern = format!(r"@{0}(?:/{0})*", segment); |
23 |
| - |
24 |
| - let re = regex::Regex::new(&pattern).unwrap(); |
25 |
| - re.replace_all(text, |caps: ®ex::Captures| { |
26 |
| - let mention = &caps[0]; |
27 |
| - let position = caps.get(0).unwrap().start(); |
28 |
| - |
29 |
| - if !is_github_mention(text, mention, position) { |
30 |
| - return mention.to_string(); |
31 |
| - } |
32 |
| - |
33 |
| - let name = &mention[1..]; // Drop the @ symbol |
34 |
| - format!("`{}`", name) |
35 |
| - }) |
36 |
| - .to_string() |
37 |
| -} |
38 |
| - |
39 |
| -// Determines if a potential mention would actually trigger a notification |
40 |
| -fn is_github_mention(text: &str, mention: &str, pos: usize) -> bool { |
41 |
| - // Not a valid mention if preceded by alphanumeric or underscore (email) |
42 |
| - if pos > 0 { |
43 |
| - let c = text.chars().nth(pos - 1).unwrap(); |
44 |
| - if c.is_alphanumeric() || c == '_' { |
45 |
| - return false; |
46 |
| - } |
47 |
| - } |
48 |
| - |
49 |
| - // Check if followed by invalid character |
50 |
| - let end = pos + mention.len(); |
51 |
| - if end < text.len() { |
52 |
| - let next_char = text.chars().nth(end).unwrap(); |
53 |
| - if next_char.is_alphanumeric() || next_char == '_' || next_char == '-' { |
54 |
| - return false; |
55 |
| - } |
56 |
| - } |
57 |
| - |
58 |
| - true |
59 |
| -} |
60 |
| - |
61 |
| -#[cfg(test)] |
62 |
| -mod tests { |
63 |
| - use super::*; |
64 |
| - |
65 |
| - #[test] |
66 |
| - fn test_suppress_github_mentions() { |
67 |
| - // User mentions |
68 |
| - assert_eq!(suppress_github_mentions("Hello @user"), "Hello `user`"); |
69 |
| - |
70 |
| - // Org team mentions |
71 |
| - assert_eq!(suppress_github_mentions("@org/team"), "`org/team`"); |
72 |
| - assert_eq!( |
73 |
| - suppress_github_mentions("@org/team/subteam"), |
74 |
| - "`org/team/subteam`" |
75 |
| - ); |
76 |
| - assert_eq!( |
77 |
| - suppress_github_mentions("@big/team/sub/group"), |
78 |
| - "`big/team/sub/group`" |
79 |
| - ); |
80 |
| - assert_eq!( |
81 |
| - suppress_github_mentions("Thanks @user, @rust-lang/libs and @github/docs/content!"), |
82 |
| - "Thanks `user`, `rust-lang/libs` and `github/docs/content`!" |
83 |
| - ); |
84 |
| - |
85 |
| - // Non mentions |
86 |
| - assert_eq!(suppress_github_mentions("@"), "@"); |
87 |
| - assert_eq!(suppress_github_mentions(""), ""); |
88 |
| - assert_eq!( |
89 |
| - suppress_github_mentions("No mentions here"), |
90 |
| - "No mentions here" |
91 |
| - ); |
92 |
| - assert_eq!( |
93 |
| - suppress_github_mentions("user@example.com"), |
94 |
| - "user@example.com" |
95 |
| - ); |
96 |
| - |
97 |
| - assert_eq!(suppress_github_mentions("@user_test"), "@user_test"); |
98 |
| - } |
99 |
| -} |
0 commit comments