Skip to main content

plot/lib/job/
step6.rs

1use std::{fs, io, path::Path};
2
3use crate::lib::{
4	job,
5	logic::{LangMapper, NodeIs},
6};
7
8// ============================================================================
9// EXPORTER (Step 6) - ZAPIS DO PLIKU MARKDOWN
10// ============================================================================
11
12pub fn engine_step6_data_save(j: &job::ValidPreparedJobConfig, formatted_rows: &[job::FormattedRow]) -> io::Result<()> {
13	// 1. Gwarantujemy istnienie folderu docelowego
14	let out_dir = &j.save.ensure_out_dir()?;
15
16	// ========================================================================
17	// ZAPIS KONFIGURACJI ZADANIA (Task.toml)
18	// ========================================================================
19	let toml_path = out_dir.join("Task.toml");
20	let toml_content = j.to_toml(
21		"auto-generated",
22		Some("Cargo-Plot Export"),
23		Some("Pełna konfiguracja użyta do wygenerowania tego zrzutu"),
24	);
25	fs::write(&toml_path, toml_content)?;
26	println!("📄 Zapisano konfigurację zadania: {}", toml_path.display());
27
28	// ========================================================================
29	// GENEROWANIE TABELI (Używamy gotowego generatora mock_render)
30	// ========================================================================
31	let table_plain_text = job::gens::mock_render(formatted_rows, &j.cols);
32
33	// ========================================================================
34	// 2. ZAPIS SOTC (INDEX) - Struktura zawartości
35	// ========================================================================
36	let sotc_path = out_dir.join(&j.save.name_index_sotc);
37	let mut sotc_content = String::new();
38
39	sotc_content.push_str(&j.save.title_index_sotc);
40	sotc_content.push_str("\n\n```plaintext\n");
41	sotc_content.push_str(&table_plain_text);
42	sotc_content.push_str("```\n");
43
44	fs::write(&sotc_path, sotc_content)?;
45	println!("📦 Zapisano SOTC (INDEX) do: {}", sotc_path.display());
46
47	// ========================================================================
48	// 3. ZAPIS COTS (FILES) - Zawartość struktury
49	// ========================================================================
50	let cots_path = out_dir.join(&j.save.name_files_cots);
51	let mut cots_content = String::new();
52
53	cots_content.push_str(&j.save.title_files_cots);
54	cots_content.push_str("\n\n");
55
56	// Parsowanie i dołączanie fizycznej zawartości plików
57	for (i, row) in formatted_rows.iter().enumerate() {
58		let n = &row.raw.node;
59		let rel_path = &n.path.str; // Ścieżka relatywna płynąca bezpośrednio z potoku
60		let actual_idx = i + 1; // Offset dla paginacji (Step 4)
61
62		if n.node == NodeIs::Dir {
63			continue;
64		}
65
66		let ext = Path::new(rel_path).extension().unwrap_or_default().to_string_lossy().to_string();
67		let lang = LangMapper::get_md_lang(&ext);
68		let is_bin = n.file_is_binary.unwrap_or(false);
69
70		if LangMapper::is_blacklisted(&ext) || is_bin {
71			cots_content.push_str(&format!(
72				"## {:03}: `{}`\n\n> *(Plik binarny/graficzny - pominięto zawartość)*\n\n",
73				actual_idx, rel_path
74			));
75			continue;
76		}
77
78		// Odczyt pliku natywnie po ścieżce z noda
79		match fs::read_to_string(rel_path) {
80			Ok(file_content) => {
81				let safe_content = file_content.replace('\t', "    ");
82				cots_content.push_str(&format!(
83					"## {:03}: `{}`\n\n```{}\n{}\n```\n\n",
84					actual_idx, rel_path, lang, safe_content
85				));
86			}
87			Err(_) => {
88				cots_content.push_str(&format!(
89					"## {:03}: `{}`\n\n> *(Błąd odczytu / plik nie jest UTF-8)*\n\n",
90					actual_idx, rel_path
91				));
92			}
93		}
94	}
95
96	fs::write(&cots_path, cots_content)?;
97	println!("📦 Zapisano COTS (FILES) do: {}", cots_path.display());
98
99	Ok(())
100}