Skip to main content

codelens_core/output/
html.rs

1//! HTML output format with interactive charts.
2
3use std::io::Write;
4
5use askama::Template;
6
7use crate::analyzer::stats::{AnalysisResult, LanguageSummary, Summary};
8use crate::error::Result;
9
10use super::format::{OutputFormat, OutputOptions};
11
12/// HTML report template.
13#[derive(Template)]
14#[template(path = "report.html")]
15struct HtmlReport<'a> {
16    title: &'a str,
17    generated_at: String,
18    summary: &'a Summary,
19    by_language: Vec<(&'a str, &'a LanguageSummary)>,
20    elapsed_secs: f64,
21}
22
23/// HTML output formatter.
24pub struct HtmlOutput;
25
26impl HtmlOutput {
27    /// Create a new HTML output formatter.
28    pub fn new() -> Self {
29        Self
30    }
31}
32
33impl Default for HtmlOutput {
34    fn default() -> Self {
35        Self::new()
36    }
37}
38
39impl OutputFormat for HtmlOutput {
40    fn name(&self) -> &'static str {
41        "html"
42    }
43
44    fn extension(&self) -> &'static str {
45        "html"
46    }
47
48    fn write(
49        &self,
50        result: &AnalysisResult,
51        options: &OutputOptions,
52        writer: &mut dyn Write,
53    ) -> Result<()> {
54        let mut by_language: Vec<_> = result
55            .summary
56            .by_language
57            .iter()
58            .map(|(k, v)| (k.as_str(), v))
59            .collect();
60
61        if let Some(n) = options.top_n {
62            by_language.truncate(n);
63        }
64
65        let report = HtmlReport {
66            title: "Codelens - Code Statistics Report",
67            generated_at: chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string(),
68            summary: &result.summary,
69            by_language,
70            elapsed_secs: result.elapsed.as_secs_f64(),
71        };
72
73        write!(writer, "{}", report.render()?)?;
74        Ok(())
75    }
76}