]> git.r.bdr.sh - rbdr/page/blobdiff - src/file_handler/file_strategies/gemini.rs
Format and lint the code
[rbdr/page] / src / file_handler / file_strategies / gemini.rs
index d8bde1434c19be4fec7af4b95dbe0310cc41778b..e987baba989aeecc7477af731480080b4a723960 100644 (file)
@@ -1,10 +1,10 @@
 pub struct Strategy {}
 
 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::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;
 
 use crate::gemini_parser::parse;
 use crate::html_renderer::render_html;
 
@@ -27,9 +27,9 @@ impl Strategy {
 }
 
 impl FileHandlerStrategy for Strategy {
 }
 
 impl FileHandlerStrategy for Strategy {
-    fn is(&self, path: &PathBuf) -> bool {
+    fn is(&self, path: &Path) -> bool {
         if let Some(extension) = path.extension() {
         if let Some(extension) = path.extension() {
-            return !path.is_dir() && extension == "gmi"
+            return !path.is_dir() && extension == "gmi";
         }
         false
     }
         }
         false
     }
@@ -39,13 +39,10 @@ impl FileHandlerStrategy for Strategy {
     }
 
     fn can_handle(&self, file_type: &FileType) -> bool {
     }
 
     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 gemini_contents = read_to_string(&file.path).unwrap();
 
         // Front matter extraction
@@ -55,14 +52,14 @@ impl FileHandlerStrategy for Strategy {
         let mut description = "";
         if let Some(slice) = lines.get(..2) {
             for line in slice.iter() {
         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;
                 }
                     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;
                 }
             }
                     continue;
                 }
             }
@@ -76,18 +73,19 @@ impl FileHandlerStrategy for Strategy {
             .replace("{{ description }}", description)
             .replace("{{ content }}", &content_html[..]);
 
             .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();
         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 gemini_contents = read_to_string(&file.path).unwrap();
 
         // Front matter extraction
@@ -95,12 +93,12 @@ impl FileHandlerStrategy for Strategy {
         let mut lines_found = 0;
         if let Some(slice) = lines.get(..2) {
             for line in slice.iter() {
         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;
                 }
                     continue;
                 }
-                if self.is_description(&line) {
-                    lines_found = lines_found + 1;
+                if self.is_description(line) {
+                    lines_found += 1;
                     continue;
                 }
             }
                     continue;
                 }
             }
@@ -108,187 +106,247 @@ impl FileHandlerStrategy for Strategy {
 
         let gemini_source = lines[lines_found..].join("\n");
 
 
         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();
         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 {
     }
 }
 
 #[cfg(test)]
 mod tests {
+    use std::fs::create_dir_all;
+
     use super::*;
     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>
+",
+        );
     }
 }
     }
 }