summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA Farzat <a@farzat.xyz>2026-06-04 06:55:08 +0300
committerA Farzat <a@farzat.xyz>2026-06-04 07:10:48 +0300
commit390b990339630c84f423b9f2c3e2623ba5299d37 (patch)
tree8cb78cd681926a2c519d1156175eef5edc2d2572
parent6c0a5c33d18de9fb56f4f3804c790a86707add75 (diff)
downloadrepo2markdown-390b990339630c84f423b9f2c3e2623ba5299d37.tar.gz
repo2markdown-390b990339630c84f423b9f2c3e2623ba5299d37.zip
Safely escape files with backticks
-rw-r--r--src/renderer.rs61
1 files changed, 60 insertions, 1 deletions
diff --git a/src/renderer.rs b/src/renderer.rs
index 518abd8..4965963 100644
--- a/src/renderer.rs
+++ b/src/renderer.rs
@@ -4,11 +4,32 @@ pub fn render(project_name: &str, files: &[(&str, &str)]) -> String {
output.push_str("\n## Files\n");
}
for (filename, content) in files {
- output.push_str(&format!("\n### {}\n```\n{}\n```\n", filename, content));
+ let outer_backticks = outer_backticks(content);
+ output.push_str(&format!(
+ "\n### {}\n{}\n{}\n{}\n",
+ filename, outer_backticks, content, outer_backticks
+ ));
}
output
}
+fn outer_backticks(contents: &str) -> String {
+ let mut max_ticks = 0;
+ let mut current_count = 0;
+ for char in contents.chars() {
+ if char == '`' {
+ current_count += 1;
+ if current_count > max_ticks {
+ max_ticks = current_count;
+ }
+ } else {
+ current_count = 0;
+ }
+ }
+ let fence_len = std::cmp::max(3, max_ticks + 1);
+ "`".repeat(fence_len)
+}
+
#[cfg(test)]
mod tests {
use super::render;
@@ -35,4 +56,42 @@ mod tests {
```\n"
);
}
+
+ #[test]
+ fn multiple_files_are_rendered_in_order() {
+ let files = vec![("main.rs", "fn main() {}"), ("lib.rs", "pub fn hello() {}")];
+
+ let output = render("Project name", &files);
+
+ assert_eq!(
+ output,
+ "# Project name\n\n\
+ ## Files\n\n\
+ ### main.rs\n\
+ ```\n\
+ fn main() {}\n\
+ ```\n\n\
+ ### lib.rs\n\
+ ```\n\
+ pub fn hello() {}\n\
+ ```\n"
+ );
+ }
+
+ #[test]
+ fn file_with_backticks_is_handled_safely() {
+ let files = vec![("example.rs", "fn main() { println!(\"``` inside\"); }")];
+
+ let output = render("Project name", &files);
+
+ assert_eq!(
+ output,
+ "# Project name\n\n\
+ ## Files\n\n\
+ ### example.rs\n\
+ ````\n\
+ fn main() { println!(\"``` inside\"); }\n\
+ ````\n"
+ );
+ }
}