Skip to main content

lib/
fn_doc_write.rs

1use crate::fn_files_blacklist::is_blacklisted_extension;
2use crate::fn_path_utils::to_display_path;
3use crate::fn_pathtype::get_file_type;
4use std::collections::HashMap;
5use std::fs;
6use std::io;
7use std::path::PathBuf;
8
9#[allow(clippy::too_many_arguments)]
10pub fn write_md(
11    out_path: &str,
12    files: &[PathBuf],
13    id_map: &HashMap<PathBuf, String>,
14    tree_text: Option<String>,
15    id_style: &str,
16    watermark: &str,
17    command_str: &Option<String>,
18    stamp: &str,
19    suffix_stamp: bool,
20    title_file: &str,
21    title_file_with_path: bool,
22) -> io::Result<()> {
23    let mut content = String::new();
24
25    // ==========================================
26    // LOGIKA TYTUŁU
27    // ==========================================
28    let mut title_line = format!("# {}", title_file);
29
30    if !suffix_stamp {
31        title_line.push_str(&format!(" {}", stamp));
32    }
33
34    if title_file_with_path {
35        title_line.push_str(&format!(" ({})", out_path));
36    }
37
38    content.push_str(&title_line);
39    content.push_str("\n\n");
40    // ==========================================
41
42    let watermark_text = "> 🚀 Raport wygenerowany przy użyciu [cargo-plot](https://crates.io/crates/cargo-plot) | Źródło: [GitHub](https://github.com/j-Cis/cargo-plot)\n\n";
43
44    // 1. Znak wodny na początku
45    if watermark == "first" {
46        content.push_str(watermark_text);
47    }
48
49    // 2. Reprodukcja komendy
50    if let Some(cmd) = command_str {
51        content.push_str(&format!("**Wywołana komenda:**\n```bash\n{}\n```\n\n", cmd));
52    }
53
54    if let Some(tree) = tree_text {
55        content.push_str("```text\n");
56        content.push_str(&tree);
57        content.push_str("```\n\n");
58    }
59
60    let current_dir = std::env::current_dir().unwrap_or_default();
61    let mut file_counter = 1;
62
63    for path in files {
64        if path.is_dir() {
65            continue;
66        }
67
68        let display_path = to_display_path(path, &current_dir);
69
70        if path.exists() {
71            let original_id = id_map
72                .get(path)
73                .cloned()
74                .unwrap_or_else(|| "BrakID".to_string());
75
76            // <-- POPRAWIONE: używamy id_style bezpośrednio
77            let header_name = match id_style {
78                "id-num" => format!("Plik-{:03}", file_counter),
79                "id-non" => "Plik".to_string(),
80                _ => format!("Plik-{}", original_id),
81            };
82            file_counter += 1;
83
84            let ext = path
85                .extension()
86                .unwrap_or_default()
87                .to_string_lossy()
88                .to_lowercase();
89            let lang = get_file_type(&ext).md_lang;
90
91            // KROK 1: Sprawdzenie czarnej listy rozszerzeń
92            if is_blacklisted_extension(&ext) {
93                content.push_str(&format!(
94                    "## {}: `{}`\n\n> *(Plik binarny/graficzny - pominięto zawartość)*\n\n",
95                    header_name, display_path
96                ));
97                continue;
98            }
99
100            // KROK 2: Bezpieczna próba odczytu zawartości
101            match fs::read_to_string(path) {
102                Ok(file_content) => {
103                    if lang == "markdown" {
104                        content.push_str(&format!("## {}: `{}`\n\n", header_name, display_path));
105                        for line in file_content.lines() {
106                            if line.trim().is_empty() {
107                                content.push_str(">\n");
108                            } else {
109                                content.push_str(&format!("> {}\n", line));
110                            }
111                        }
112                        content.push_str("\n\n");
113                    } else {
114                        content.push_str(&format!(
115                            "## {}: `{}`\n\n```{}\n{}\n```\n\n",
116                            header_name, display_path, lang, file_content
117                        ));
118                    }
119                }
120                Err(_) => {
121                    // Fallback: Plik nie ma rozszerzenia binarnego, ale jego zawartość to nie jest czysty tekst UTF-8
122                    content.push_str(&format!("## {}: `{}`\n\n> *(Nie można odczytać pliku jako tekst UTF-8 - pominięto)*\n\n", header_name, display_path));
123                }
124            }
125        } else {
126            content.push_str(&format!(
127                "## BŁĄD: `{}` (Plik nie istnieje)\n\n",
128                display_path
129            ));
130        }
131    }
132
133    // 3. Znak wodny na końcu (Domyślnie)
134    if watermark == "last" {
135        content.push_str("---\n");
136        content.push_str(watermark_text);
137    }
138
139    fs::write(out_path, &content)?;
140    Ok(())
141}