use std::{ io::{Read, Write}, path::Path, }; use crate::{logger::Logger, run::run, util::fence::generate_outer_backticks}; pub fn wrap_in_md_fence( input: R, mut output: W, root: &Path, origin_base: &Path, project_title: Option<&str>, logger: Logger, ) -> Result<(), Box> { let mut md_output = Vec::new(); run( input, &mut md_output, root, origin_base, project_title, logger, )?; let fence = generate_outer_backticks(&md_output); writeln!(output, "{}markdown", fence)?; output.write_all(&md_output)?; writeln!(output, "{}", fence)?; Ok(()) } #[cfg(test)] mod tests { use std::fs; use std::io::{Cursor, Read, Write}; use tempfile::tempdir; use crate::logger::Logger; use super::wrap_in_md_fence; fn wrap_with_default_logger( input: R, output: W, root: &std::path::Path, origin_base: &std::path::Path, project_title: Option<&str>, ) -> Result<(), Box> { let logger = Logger::default(); wrap_in_md_fence(input, output, root, origin_base, project_title, logger) } #[test] fn empty_input_produces_wrapped_header() { let temp_dir = tempdir().unwrap(); let input = Cursor::new(b""); let mut output = Vec::new(); let root = temp_dir.path(); let origin_base = temp_dir.path(); wrap_with_default_logger(input, &mut output, root, origin_base, Some("Project name")) .unwrap(); assert_eq!( String::from_utf8(output).unwrap(), "```markdown\n# Project name\n```\n" ); } #[test] fn single_file_is_wrapped() { let temp_dir = tempdir().unwrap(); let origin_base = temp_dir.path(); let input = Cursor::new(b"test_main.rs\0"); let mut output = Vec::new(); let root = temp_dir.path(); fs::write(origin_base.join("test_main.rs"), "fn main() {}").unwrap(); wrap_with_default_logger(input, &mut output, root, origin_base, None).unwrap(); let output_str = String::from_utf8(output).unwrap(); // Must contain outer fence assert!(output_str.starts_with("````markdown\n")); assert!(output_str.ends_with("\n````\n")); // Must contain file content assert!(output_str.contains("## File: test_main.rs")); assert!(output_str.contains("fn main() {}")); } #[test] fn multiple_files_are_enveloped_using_only_one_outer_fence_while_each_having_its_own_fence() { let temp_dir = tempdir().unwrap(); let origin_base = temp_dir.path(); let input = Cursor::new(b"a.rs\0b.rs\0"); let mut output = Vec::new(); let root = temp_dir.path(); fs::write(origin_base.join("a.rs"), "A").unwrap(); fs::write(origin_base.join("b.rs"), "B").unwrap(); wrap_with_default_logger(input, &mut output, root, origin_base, None).unwrap(); let output_str = String::from_utf8(output).unwrap(); // Each inner file must have its own language‑specific fence assert!(output_str.contains("```rust\nA\n```")); assert!(output_str.contains("```rust\nB\n```")); // Only one outer fence at start and end assert_eq!(output_str.matches("````markdown").count(), 1); assert_eq!(output_str.matches("\n````\n").count(), 1); } #[test] fn inner_file_with_four_backticks_causes_outer_fence_of_six_backticks() { let temp_dir = tempdir().unwrap(); let origin_base = temp_dir.path(); let input = Cursor::new(b"backticks.rs\0"); let mut output = Vec::new(); let root = temp_dir.path(); let content = "````"; // 4 backticks fs::write(origin_base.join("backticks.rs"), content).unwrap(); wrap_with_default_logger(input, &mut output, root, origin_base, None).unwrap(); let output_str = String::from_utf8(output).unwrap(); // Inner fence should be 5 backticks because inner content contains 4 backticks assert!(output_str.contains("`````rust\n````\n`````")); // Outer fence must then be 6 backticks assert!(output_str.starts_with("``````markdown\n")); assert!(output_str.ends_with("\n``````\n")); } #[test] fn project_title_with_three_backticks_causes_outer_fence_of_four_backticks() { let temp_dir = tempdir().unwrap(); let input = Cursor::new(b""); let mut output = Vec::new(); let root = temp_dir.path(); let origin_base = temp_dir.path(); let project_title = "Project ``` name"; wrap_with_default_logger(input, &mut output, root, origin_base, Some(project_title)) .unwrap(); let output_str = String::from_utf8(output).unwrap(); // Outer fence must be 4 backticks because the header contains 3 backticks assert!(output_str.starts_with("````markdown\n")); assert!(output_str.ends_with("\n````\n")); // The header line itself should appear unchanged assert!(output_str.contains("# Project ``` name")); } }