Skip to main content

ktrs_cli/ktlint/reporter/
html.rs

1//! Port of `ktlint-cli-reporter-html` (`HtmlReporter`, MIT, (c) 2019 Matheus Candido).
2
3use crate::ktlint::console::{LINE_SEPARATOR, Printer};
4use crate::ktlint::reporter::java_map::JavaConcurrentHashMap;
5use crate::ktlint::reporter::{KtlintCliError, ReporterV2, Status, escape_xml_attr_value};
6
7pub struct HtmlReporter {
8    out: Printer,
9    acc: JavaConcurrentHashMap<Vec<KtlintCliError>>,
10    issue_count: usize,
11    corrected_count: usize,
12}
13
14impl HtmlReporter {
15    pub fn new(out: Printer) -> HtmlReporter {
16        HtmlReporter { out, acc: JavaConcurrentHashMap::new(), issue_count: 0, corrected_count: 0 }
17    }
18
19    fn head(&mut self) {
20        let out = &mut self.out;
21        out.println("<head>");
22        out.print("<link href=\"");
23        out.print("https://fonts.googleapis.com/css?family=Source+Code+Pro");
24        out.println("\" rel=\"stylesheet\" />");
25        out.print(&format!("<meta http-equiv=\"Content-Type\" Content=\"text/html; Charset=UTF-8\">{LINE_SEPARATOR}"));
26        out.print(&format!("<style>{LINE_SEPARATOR}"));
27        out.print(&format!("body {{{LINE_SEPARATOR}"));
28        out.print(&format!("    font-family: 'Source Code Pro', monospace;{LINE_SEPARATOR}"));
29        out.print(&format!("}}{LINE_SEPARATOR}"));
30        out.print(&format!("h3 {{{LINE_SEPARATOR}"));
31        out.print(&format!("    font-size: 12pt;{LINE_SEPARATOR}"));
32        out.print("}");
33        out.print(&format!("</style>{LINE_SEPARATOR}"));
34        out.println("</head>");
35    }
36
37    fn body(&mut self) {
38        let out = &mut self.out;
39        out.println("<body>");
40        if !self.acc.is_empty() {
41            out.print("<h1>");
42            out.print("Overview");
43            out.println("</h1>");
44            paragraph(out, &format!("Issues found: {}", self.issue_count));
45            paragraph(out, &format!("Issues corrected: {}", self.corrected_count));
46            for (file, errors) in self.acc.iter() {
47                out.print("<h3>");
48                out.print(file);
49                out.println("</h3>");
50                out.println("<ul>");
51                for err in errors {
52                    out.print("<li>");
53                    out.print(&escape_xml_attr_value(&format!(
54                        "({}, {}): {}  ({})",
55                        err.line, err.col, err.detail, err.rule_id
56                    )));
57                    out.println("</li>");
58                }
59                out.println("</ul>");
60            }
61        } else {
62            paragraph(out, "Congratulations, no issues found!");
63        }
64        out.println("</body>");
65    }
66}
67
68fn paragraph(out: &mut Printer, text: &str) {
69    out.print("<p>");
70    out.print(text);
71    out.println("</p>");
72}
73
74impl ReporterV2 for HtmlReporter {
75    fn on_lint_error(&mut self, file: &str, ktlint_cli_error: &KtlintCliError) {
76        if ktlint_cli_error.status != Status::FormatIsAutocorrected {
77            self.issue_count += 1;
78            self.acc.get_or_put(file, Vec::new).push(ktlint_cli_error.clone());
79        } else {
80            self.corrected_count += 1;
81        }
82    }
83
84    fn after_all(&mut self) {
85        self.out.println("<html>");
86        self.head();
87        self.body();
88        self.out.println("</html>");
89    }
90}