Format a message for GitHub Actions workflow commands. Newlines are encoded as `%0A` per the GitHub Actions spec, and `@mentions` are wrapped in backticks to prevent GitHub from sending notifications (matching PHPStan's `GithubErrorFormatter` behaviour).
(message: &str)
| 811 | /// are wrapped in backticks to prevent GitHub from sending notifications |
| 812 | /// (matching PHPStan's `GithubErrorFormatter` behaviour). |
| 813 | pub(crate) fn format_github_message(message: &str) -> String { |
| 814 | let message = message.replace('\n', "%0A"); |
| 815 | // Wrap @mentions in backticks to prevent GitHub notifications. |
| 816 | let mut result = String::with_capacity(message.len()); |
| 817 | let mut chars = message.char_indices().peekable(); |
| 818 | let mut last_end = 0; |
| 819 | while let Some((i, c)) = chars.next() { |
| 820 | if c == '@' { |
| 821 | let before_is_space = i == 0 |
| 822 | || message |
| 823 | .as_bytes() |
| 824 | .get(i - 1) |
| 825 | .is_none_or(|b| b.is_ascii_whitespace()); |
| 826 | if before_is_space { |
| 827 | // Collect the mention: @[a-zA-Z0-9_-]+ |
| 828 | let start = i + 1; |
| 829 | let mut end = start; |
| 830 | while let Some(&(j, nc)) = chars.peek() { |
| 831 | if nc.is_ascii_alphanumeric() || nc == '_' || nc == '-' { |
| 832 | end = j + nc.len_utf8(); |
| 833 | chars.next(); |
| 834 | } else { |
| 835 | break; |
| 836 | } |
| 837 | } |
| 838 | if end > start { |
| 839 | result.push_str(&message[last_end..i]); |
| 840 | result.push('`'); |
| 841 | result.push_str(&message[i..end]); |
| 842 | result.push('`'); |
| 843 | last_end = end; |
| 844 | continue; |
| 845 | } |
| 846 | } |
| 847 | } |
| 848 | } |
| 849 | result.push_str(&message[last_end..]); |
| 850 | result |
| 851 | } |
| 852 | |
| 853 | // ── JSON output ───────────────────────────────────────────────────────────── |
| 854 |
no test coverage detected