Skip to main content

react_auditor/formatters/
stylish.rs

1use std::io::Write;
2
3use termcolor::{Buffer, Color, ColorSpec, WriteColor};
4
5use crate::formatters::Formatter;
6use crate::rules::Severity;
7use crate::scanner::ScanResult;
8
9pub struct StylishFormatter;
10
11impl Formatter for StylishFormatter {
12    fn format(&self, results: &[ScanResult], quiet: bool) -> String {
13        let mut buf = Buffer::ansi();
14        let mut error_count = 0u32;
15        let mut warning_count = 0u32;
16
17        for result in results {
18            let violations: Vec<_> = result
19                .violations
20                .iter()
21                .filter(|v| {
22                    if quiet {
23                        v.severity == Severity::Error
24                    } else {
25                        true
26                    }
27                })
28                .collect();
29
30            if violations.is_empty() {
31                continue;
32            }
33
34            let _ = writeln!(buf, "\n{}:", result.file_path);
35
36            for v in &violations {
37                let (severity_str, color) = match v.severity {
38                    Severity::Error => {
39                        error_count += 1;
40                        ("error", Color::Red)
41                    }
42                    Severity::Warning => {
43                        warning_count += 1;
44                        ("warning", Color::Yellow)
45                    }
46                    Severity::Off => continue,
47                };
48
49                let _ = buf.set_color(ColorSpec::new().set_fg(Some(Color::Cyan)));
50                let _ = write!(buf, "  {severity_str}  {}:{}  ", v.line, v.column);
51                let _ = buf.set_color(ColorSpec::new().set_fg(Some(Color::Blue)));
52                let _ = write!(buf, "[{}/{}]", v.category, v.rule_id);
53                let _ = buf.set_color(ColorSpec::new().set_fg(Some(color)));
54                let _ = write!(buf, "  {}", v.message);
55                let _ = buf.reset();
56                let _ = writeln!(buf);
57            }
58        }
59
60        let total = error_count + warning_count;
61        if total > 0 {
62            let _ = writeln!(buf);
63            if error_count > 0 {
64                let _ = buf.set_color(ColorSpec::new().set_fg(Some(Color::Red)).set_bold(true));
65                let _ = writeln!(buf, "  {error_count} error(s)");
66            }
67            if warning_count > 0 {
68                let _ = buf.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)).set_bold(true));
69                let _ = writeln!(buf, "  {warning_count} warning(s)");
70            }
71            let _ = buf.reset();
72        }
73
74        String::from_utf8(buf.into_inner()).unwrap_or_default()
75    }
76}