## Hidden folders
-Hidden folders get ignored, except for the .well-known folder.
+Hidden folders are copied as well, we only make an exception for `.git`, which
+is explicitly ignored. This is handy for folders like .well-known, but could
+cause unwanted behavior if there's other hidden files in the directory.
## What happens to files that aren't gemini?
use std::fs::read_dir;
use std::path::PathBuf;
-pub fn find_files(directory_path: PathBuf) -> Vec<File> {
- return find_files_recursively(&directory_path, &directory_path);
+pub fn find_files(directory_path: &PathBuf) -> Vec<File> {
+ return find_files_recursively(directory_path, directory_path);
}
fn find_files_recursively(root_path: &PathBuf, directory_path: &PathBuf) -> Vec<File> {
for entry in entries {
let path = entry.unwrap().path();
let relative_path = path.strip_prefix(&root_path).unwrap();
- if relative_path.starts_with(".") && !relative_path.starts_with(".well-known") {
+ if relative_path.starts_with(".git") {
continue;
}
if path.is_dir() {
use std::path::PathBuf;
-use crate::file_handler::{FileType, FileHandlerStrategy};
+use crate::file_handler::{File, FileType, FileHandlerStrategy};
impl FileHandlerStrategy for Strategy {
fn is(&self, path: &PathBuf) -> bool {
FileType::File
}
- fn can_handle(&self, path: &PathBuf) -> bool {
- self.is(path)
+ fn can_handle(&self, file_type: &FileType) -> bool {
+ match file_type {
+ FileType::File => true,
+ _ => false,
+ }
}
- fn handle(&self, path: &PathBuf) {
- println!("Should copy {}", path.display())
+ fn handle(&self, file: &File) {
+ println!("Should copy {}", file.path.display())
}
}
use std::path::PathBuf;
-use crate::file_handler::{FileType, FileHandlerStrategy};
+use crate::file_handler::{File, FileType, FileHandlerStrategy};
impl FileHandlerStrategy for Strategy {
fn is(&self, path: &PathBuf) -> bool {
FileType::Gemini
}
- fn can_handle(&self, path: &PathBuf) -> bool {
- self.is(path)
+ fn can_handle(&self, file_type: &FileType) -> bool {
+ match file_type {
+ FileType::Gemini => true,
+ _ => false,
+ }
}
- fn handle(&self, path: &PathBuf) {
- println!("Should convert {}", path.display())
+ fn handle(&self, file: &File) {
+ println!("Should parse and copy {}", file.path.display())
}
}
use std::path::PathBuf;
-use crate::file_handler::{FileType, FileHandlerStrategy};
+use crate::file_handler::{File, FileType, FileHandlerStrategy};
impl FileHandlerStrategy for Strategy {
fn is(&self, path: &PathBuf) -> bool {
FileType::Layout
}
- fn can_handle(&self, path: &PathBuf) -> bool {
- self.is(path)
+ fn can_handle(&self, file_type: &FileType) -> bool {
+ match file_type {
+ FileType::Layout => true,
+ _ => false,
+ }
}
- fn handle(&self, path: &PathBuf) {
- println!("Should convert {}", path.display())
- }
+ fn handle(&self, _file: &File) {}
}
-
use file_strategies::layout::Strategy as LayoutStrategy;
use std::path::PathBuf;
+use std::fs::read_to_string;
pub struct FileHandler {
- pub strategies: Vec<Box<dyn FileHandlerStrategy>>
+ pub strategies: Vec<Box<dyn FileHandlerStrategy>>,
+ pub layout: Option<String>
}
impl Default for FileHandler {
Box::new(GeminiStrategy{}),
Box::new(LayoutStrategy{}),
Box::new(FileStrategy{}),
- ]
+ ],
+ layout: None
}
}
}
FileType::Unknown
}
- pub fn handle(&self, path: &PathBuf) {
+ pub fn get_layout_or_panic(&mut self, files: &Vec<File>) {
+ for file in files {
+ match file.file_type {
+ FileType::Layout => {
+ let layout_text = read_to_string(&file.path).unwrap();
+ self.layout = Some(layout_text);
+ return;
+ },
+ _ => {}
+ }
+ }
+ panic!("No layout found. Please ensure there's a _layout.html file at the root");
+ }
+
+ pub fn handle_all(&self, source: &PathBuf, destination: &PathBuf, files: &Vec<File>) {
+ for file in files {
+ self.handle(source, destination, file);
+ }
+ }
+
+ pub fn handle(&self, source: &PathBuf, destination: &PathBuf, file: &File) {
for strategy in self.strategies.iter() {
- if strategy.can_handle(path) {
- return strategy.handle(path);
+ if strategy.can_handle(&file.file_type) {
+ return strategy.handle(file);
}
}
}
pub trait FileHandlerStrategy {
fn is(&self, path: &PathBuf) -> bool;
fn identify(&self) -> FileType;
- fn can_handle(&self, path: &PathBuf) -> bool;
- fn handle(&self, path: &PathBuf);
+ fn can_handle(&self, file_type: &FileType) -> bool;
+ fn handle(&self, file: &File);
}
pub enum FileType {
mod file_finder;
mod file_handler;
+use std::io::Result;
use std::env::current_dir;
+use std::fs::create_dir_all;
use crate::gemini_parser::parse;
use crate::file_finder::find_files;
+use crate::file_handler::FileHandler;
-fn main() {
+fn main() -> Result<()> {
let gemini_source = "# Test\n## 2nd H\na line\n another line\n```\npreformat\n=> preformat\n```\n=> http://lol.com\n=> http://lol.com lol\n* lol\nbla\n* lol\n* lmao\n> blabla\n> blabla";
let html = parse(gemini_source);
println!("{}", html);
- let files = find_files(current_dir().unwrap());
+ let source = current_dir()?;
+ let source_name = source.file_name().unwrap().to_string_lossy();
+ let parent = source.parent().unwrap();
+ let destination_name = format!("{}_html", source_name);
+ let destination = parent.join(destination_name);
+
+ // Step 1. Identify the files
+ let files = find_files(&source);
+
+ // Step 2. Prepare the target priority
+ create_dir_all(&destination)?;
+
println!("Found {} files", files.len());
+
+ // Step 3. Load the layout
+ let mut file_handler = FileHandler::default();
+ file_handler.get_layout_or_panic(&files);
+
+ // Step 4. Process all files
+ file_handler.handle_all(&source, &destination, &files);
+ Ok(())
}