pub struct Strategy {}
-use std::path::PathBuf;
-use std::io::Write;
use std::fs::{create_dir_all, read_to_string, File as IOFile};
+use std::io::Write;
+use std::path::Path;
-use crate::file_handler::{File, FileType, FileHandlerStrategy};
+use crate::file_handler::{File, FileHandlerStrategy, FileType};
use crate::gemini_parser::parse;
use crate::html_renderer::render_html;
}
impl FileHandlerStrategy for Strategy {
- fn is(&self, path: &PathBuf) -> bool {
+ fn is(&self, path: &Path) -> bool {
if let Some(extension) = path.extension() {
- return !path.is_dir() && extension == "gmi"
+ return !path.is_dir() && extension == "gmi";
}
false
}
}
fn can_handle(&self, file_type: &FileType) -> bool {
- match file_type {
- FileType::Gemini => true,
- _ => false,
- }
+ matches!(file_type, FileType::Gemini)
}
- fn handle_html(&self, source: &PathBuf, destination: &PathBuf, file: &File, layout: &str) {
+ fn handle_html(&self, source: &Path, destination: &Path, file: &File, layout: &str) {
let gemini_contents = read_to_string(&file.path).unwrap();
// Front matter extraction
let mut description = "";
if let Some(slice) = lines.get(..2) {
for line in slice.iter() {
- if self.is_title(&line) {
- title = self.get_title(&line).trim();
- lines_found = lines_found + 1;
+ if self.is_title(line) {
+ title = self.get_title(line).trim();
+ lines_found += 1;
continue;
}
- if self.is_description(&line) {
- description = self.get_description(&line).trim();
- lines_found = lines_found + 1;
+ if self.is_description(line) {
+ description = self.get_description(line).trim();
+ lines_found += 1;
continue;
}
}
.replace("{{ description }}", description)
.replace("{{ content }}", &content_html[..]);
-
- let relative_path = file.path.strip_prefix(&source).unwrap();
+ let relative_path = file.path.strip_prefix(source).unwrap();
let mut complete_destination = destination.join(relative_path);
complete_destination.set_extension("html");
let destination_parent = complete_destination.parent().unwrap();
create_dir_all(destination_parent).unwrap();
let mut destination_file = IOFile::create(&complete_destination).unwrap();
- destination_file.write_all(generated_html.as_bytes()).unwrap();
+ destination_file
+ .write_all(generated_html.as_bytes())
+ .unwrap();
}
- fn handle_gemini(&self, source: &PathBuf, destination: &PathBuf, file: &File) {
+ fn handle_gemini(&self, source: &Path, destination: &Path, file: &File) {
let gemini_contents = read_to_string(&file.path).unwrap();
// Front matter extraction
let mut lines_found = 0;
if let Some(slice) = lines.get(..2) {
for line in slice.iter() {
- if self.is_title(&line) {
- lines_found = lines_found + 1;
+ if self.is_title(line) {
+ lines_found += 1;
continue;
}
- if self.is_description(&line) {
- lines_found = lines_found + 1;
+ if self.is_description(line) {
+ lines_found += 1;
continue;
}
}
let gemini_source = lines[lines_found..].join("\n");
- let relative_path = file.path.strip_prefix(&source).unwrap();
+ let relative_path = file.path.strip_prefix(source).unwrap();
let complete_destination = destination.join(relative_path);
let destination_parent = complete_destination.parent().unwrap();
create_dir_all(destination_parent).unwrap();
let mut destination_file = IOFile::create(&complete_destination).unwrap();
- destination_file.write_all(gemini_source.as_bytes()).unwrap();
+ destination_file
+ .write_all(gemini_source.as_bytes())
+ .unwrap();
}
}
#[cfg(test)]
mod tests {
+ use std::fs::create_dir_all;
+
use super::*;
- use std::fs;
- fn setup() -> Strategy {
- Strategy {}
- }
+ use test_utilities::*;
- fn fixtures_dir() -> PathBuf {
- PathBuf::from("tests/fixtures")
+ #[test]
+ fn detects_title() {
+ let strategy = Strategy {};
+ assert!(strategy.is_title("--- title: Hello!"));
}
- fn fixture_path(filename: &str) -> PathBuf {
- fixtures_dir().join(filename)
+ #[test]
+ fn does_not_detect_other_keys_as_title() {
+ let strategy = Strategy {};
+ assert!(!strategy.is_title("--- description: Hello!"));
}
- fn read_fixture(filename: &str) -> String {
- fs::read_to_string(fixture_path(filename))
- .unwrap_or_else(|_| panic!("Failed to read fixture file: {}", filename))
+ #[test]
+ fn detects_description() {
+ let strategy = Strategy {};
+ assert!(strategy.is_description("--- description: What is this?"));
}
- mod front_matter_tests {
- use super::*;
-
- #[test]
- fn detects_title() {
- let strategy = setup();
- let content = read_fixture("test1.gmi");
- let first_line = content.lines().next().unwrap();
- assert!(strategy.is_title(first_line));
- }
-
- #[test]
- fn detects_description() {
- let strategy = setup();
- let content = read_fixture("test1.gmi");
- let second_line = content.lines().nth(1).unwrap();
- assert!(strategy.is_description(second_line));
- }
-
- #[test]
- fn extracts_title() {
- let strategy = setup();
- let content = read_fixture("test1.gmi");
- let first_line = content.lines().next().unwrap();
- assert_eq!(strategy.get_title(first_line).trim(), "Test Title");
- }
-
- #[test]
- fn extracts_description() {
- let strategy = setup();
- let content = read_fixture("test1.gmi");
- let second_line = content.lines().nth(1).unwrap();
- assert_eq!(strategy.get_description(second_line).trim(), "Test Description");
- }
+ #[test]
+ fn does_not_detect_other_keys_as_description() {
+ let strategy = Strategy {};
+ assert!(!strategy.is_description("--- title: What is this?"));
}
- mod file_type_tests {
- use super::*;
-
- #[test]
- fn identifies_gemini_files() {
- let strategy = setup();
- assert!(strategy.is(&fixture_path("test1.gmi")));
- assert!(!strategy.is(&fixture_path("_layout.html")));
- assert!(!strategy.is(&fixtures_dir()));
- }
-
- #[test]
- fn identifies_file_type() {
- let strategy = setup();
- assert!(matches!(strategy.identify(), FileType::Gemini));
- }
+ #[test]
+ fn extracts_title() {
+ let strategy = Strategy {};
+ assert_eq!(strategy.get_title("--- title: Hello!").trim(), "Hello!");
+ }
- #[test]
- fn handles_correct_file_type() {
- let strategy = setup();
- assert!(strategy.can_handle(&FileType::Gemini));
- assert!(!strategy.can_handle(&FileType::Layout));
- assert!(!strategy.can_handle(&FileType::File));
- assert!(!strategy.can_handle(&FileType::Unknown));
- }
+ #[test]
+ fn extracts_description() {
+ let strategy = Strategy {};
+ assert_eq!(
+ strategy
+ .get_description("--- description: What is this?")
+ .trim(),
+ "What is this?"
+ );
}
- mod file_handling_tests {
- use super::*;
-
- #[test]
- fn handles_html_generation() {
- let strategy = setup();
- let source = fixtures_dir();
- let output = fixture_path("output");
- let layout = read_fixture("_layout.html");
-
- let file = File {
- path: fixture_path("test1.gmi"),
- file_type: FileType::Gemini,
- };
-
- strategy.handle_html(
- &source,
- &output,
- &file,
- &layout,
- );
-
- let generated_path = output.join("test1.html");
- assert!(generated_path.exists());
-
- let content = fs::read_to_string(generated_path.clone()).unwrap();
- assert!(content.contains("Test Title"));
- assert!(content.contains("<h1>"));
-
- // Cleanup
- let _ = fs::remove_file(generated_path);
- }
+ #[test]
+ fn identifies_gemini_file() {
+ let test_dir = setup_test_dir();
+ create_test_file(&test_dir.join("test.gmi"), "");
+ let strategy = Strategy {};
+ assert!(strategy.is(&test_dir.join("test.gmi")));
+ }
- #[test]
- fn handles_gemini_generation() {
- let strategy = setup();
- let source = fixtures_dir();
- let output = fixture_path("output");
+ #[test]
+ fn rejects_non_gemini_file() {
+ let test_dir = setup_test_dir();
+ create_test_file(&test_dir.join("_layout.html"), "");
+ create_test_file(&test_dir.join("image.png"), "");
+ let strategy = Strategy {};
+ assert!(!strategy.is(&test_dir.join("_layout.html")));
+ assert!(!strategy.is(&test_dir.join("image.png")));
+ assert!(!strategy.is(&test_dir));
+ }
- let file = File {
- path: fixture_path("test1.gmi"),
- file_type: FileType::Gemini,
- };
+ #[test]
+ fn identifies_gemini_type() {
+ let strategy = Strategy {};
+ assert!(matches!(strategy.identify(), FileType::Gemini));
+ }
- strategy.handle_gemini(
- &source,
- &output,
- &file,
- );
+ #[test]
+ fn handles_gemini_type() {
+ let strategy = Strategy {};
+ assert!(strategy.can_handle(&FileType::Gemini));
+ }
- let generated_path = output.join("test1.gmi");
- assert!(generated_path.exists());
+ #[test]
+ fn rejects_non_gemini_types() {
+ let strategy = Strategy {};
+ assert!(!strategy.can_handle(&FileType::Layout));
+ assert!(!strategy.can_handle(&FileType::File));
+ assert!(!strategy.can_handle(&FileType::Unknown));
+ }
- let content = fs::read_to_string(&generated_path).unwrap();
- assert!(content.contains("# Heading"));
- assert!(!content.contains("Test Title")); // Front matter should be removed
+ #[test]
+ fn handles_html_generation() {
+ let test_dir = setup_test_dir();
+ let source_dir = test_dir.join("source");
+ let output_dir = test_dir.join("output");
+ create_dir_all(&source_dir).expect("Could not create source test directory");
+ create_dir_all(&output_dir).expect("Could not create output test directory");
+ let layout = "\
+<html>
+<head>
+<title>{{ title }}</title>
+<meta name=\"description\" content=\"{{ description }}\">
+</head>
+<body>{{ content }}</body>
+</html>
+";
+ create_test_file(
+ &source_dir.join("test.gmi"),
+ "\
+--- title: Page Is Cool!
+--- description: My Description
+# Test
+Hello world
+",
+ );
+
+ let strategy = Strategy {};
+ let file = File {
+ path: source_dir.join("test.gmi"),
+ file_type: FileType::Gemini,
+ };
+
+ strategy.handle_html(&source_dir, &output_dir, &file, &layout);
+
+ let html_output = output_dir.join("test.html");
+ assert!(html_output.exists());
+ assert_file_contents(
+ &html_output,
+ "\
+<html>
+<head>
+<title>Page Is Cool!</title>
+<meta name=\"description\" content=\"My Description\">
+</head>
+<body><section class=\"h1\">
+<h1> Test</h1>
+<p>Hello world</p>
+</section>
+</body>
+</html>
+",
+ );
+ }
- // Cleanup
- let _ = fs::remove_file(generated_path);
- }
+ #[test]
+ fn handles_gemini_generation() {
+ let test_dir = setup_test_dir();
+ let source_dir = test_dir.join("source");
+ let output_dir = test_dir.join("output");
+ create_dir_all(&source_dir).expect("Could not create source test directory");
+ create_dir_all(&output_dir).expect("Could not create output test directory");
+ create_test_file(
+ &source_dir.join("test.gmi"),
+ "\
+--- title: Page Is Cool!
+--- description: My Description
+# Test
+Hello world
+",
+ );
+
+ let strategy = Strategy {};
+ let file = File {
+ path: source_dir.join("test.gmi"),
+ file_type: FileType::Gemini,
+ };
+
+ strategy.handle_gemini(&source_dir, &output_dir, &file);
+
+ let gemini_output = output_dir.join("test.gmi");
+ assert!(gemini_output.exists());
+ assert_file_contents(
+ &gemini_output,
+ "\
+# Test
+Hello world
+",
+ );
+ }
- #[test]
- fn handles_nested_structure() {
- let strategy = setup();
- let source = fixtures_dir();
- let output = fixture_path("output");
- let layout = read_fixture("_layout.html");
-
- let file = File {
- path: fixture_path("nested/nested.gmi"),
- file_type: FileType::Gemini,
- };
-
- strategy.handle_html(
- &source,
- &output,
- &file,
- &layout,
- );
-
- let generated_path = output.join("nested").join("nested.html");
- assert!(generated_path.exists());
-
- // Cleanup
- let _ = fs::remove_file(generated_path);
- let _ = fs::remove_dir(output.join("nested"));
- }
+ #[test]
+ fn handles_nested_structure() {
+ let test_dir = setup_test_dir();
+ let source_dir = test_dir.join("source");
+ let output_dir = test_dir.join("output");
+ create_dir_all(&source_dir.join("nested")).expect("Could not create source test directory");
+ create_dir_all(&output_dir).expect("Could not create output test directory");
+ let layout = "\
+<html>
+<head>
+<title>{{ title }}</title>
+<meta name=\"description\" content=\"{{ description }}\">
+</head>
+<body>{{ content }}</body>
+</html>
+";
+ create_test_file(
+ &source_dir.join("nested/test.gmi"),
+ "\
+--- title: Page Is Cool!
+--- description: My Description
+# Test
+Hello world
+",
+ );
+
+ let strategy = Strategy {};
+ let file = File {
+ path: source_dir.join("nested/test.gmi"),
+ file_type: FileType::Gemini,
+ };
+
+ strategy.handle_html(&source_dir, &output_dir, &file, &layout);
+
+ let html_output = output_dir.join("nested/test.html");
+ assert!(html_output.exists());
+ assert_file_contents(
+ &html_output,
+ "\
+<html>
+<head>
+<title>Page Is Cool!</title>
+<meta name=\"description\" content=\"My Description\">
+</head>
+<body><section class=\"h1\">
+<h1> Test</h1>
+<p>Hello world</p>
+</section>
+</body>
+</html>
+",
+ );
}
}