~rbdr/page

68fa37d61babe8d990ace5f9cb5a7de81eb57ea0 — Ruben Beltran del Rio 1 year, 2 months ago 4cbe653
Add gemini parsing
M src/file_handler/file_strategies/file.rs => src/file_handler/file_strategies/file.rs +1 -1
@@ 21,7 21,7 @@ impl FileHandlerStrategy for Strategy {
        }
    }

    fn handle(&self, source: &PathBuf, destination: &PathBuf, file: &File) {
    fn handle(&self, source: &PathBuf, destination: &PathBuf, file: &File, _l: &String) {
        let relative_path = file.path.strip_prefix(&source).unwrap();
        let complete_destination = destination.join(relative_path);
        let destination_parent = complete_destination.parent().unwrap();

M src/file_handler/file_strategies/gemini.rs => src/file_handler/file_strategies/gemini.rs +58 -2
@@ 1,8 1,29 @@
pub struct Strategy {}

use std::path::PathBuf;
use std::io::Write;
use std::fs::{create_dir_all, read_to_string, File as IOFile};

use crate::file_handler::{File, FileType, FileHandlerStrategy};
use crate::gemini_parser::parse;

impl Strategy {
    fn is_title(&self, line: &str) -> bool {
        line.starts_with("--- title:")
    }

    fn is_description(&self, line: &str) -> bool {
        line.starts_with("--- description:")
    }

    fn get_title<'a>(&self, line: &'a str) -> &'a str {
        line.split_once("--- title:").unwrap().1
    }

    fn get_description<'a>(&self, line: &'a str) -> &'a str {
        line.split_once("--- description:").unwrap().1
    }
}

impl FileHandlerStrategy for Strategy {
    fn is(&self, path: &PathBuf) -> bool {


@@ 23,7 44,42 @@ impl FileHandlerStrategy for Strategy {
        }
    }

    fn handle(&self, source: &PathBuf, destination: &PathBuf, file: &File) {
        println!("Should parse and copy {}", file.path.display())
    fn handle(&self, source: &PathBuf, destination: &PathBuf, file: &File, layout: &String) {
        let gemini_contents = read_to_string(&file.path).unwrap();

        // Front matter extraction
        let lines: Vec<&str> = gemini_contents.split("\n").collect();
        let mut lines_found = 0;
        let mut title = "";
        let mut description = "";
        for line in lines[..2].iter() {
            if self.is_title(&line) {
                title = self.get_title(&line).trim();
                lines_found = lines_found + 1;
                continue;
            }
            if self.is_description(&line) {
                description = self.get_description(&line).trim();
                lines_found = lines_found + 1;
                continue;
            }
        }

        let gemini_source = lines[lines_found..].join("\n");
        let content_html = parse(&gemini_source[..]);

        let generated_html = layout
            .replace("{{ title }}", title)
            .replace("{{ description }}", description)
            .replace("{{ content }}", &content_html[..]);


        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(generated_html.as_bytes()).unwrap();
    }
}

M src/file_handler/file_strategies/layout.rs => src/file_handler/file_strategies/layout.rs +1 -1
@@ 22,5 22,5 @@ impl FileHandlerStrategy for Strategy {

    // We don't implement handling for layout, as we assume there's only one
    // and it got handled before.
    fn handle(&self, _s: &PathBuf, _d: &PathBuf, _f: &File) {}
    fn handle(&self, _s: &PathBuf, _d: &PathBuf, _f: &File, _l: &String) {}
}

M src/file_handler/mod.rs => src/file_handler/mod.rs +3 -2
@@ 58,7 58,8 @@ impl FileHandler {
    pub fn handle(&self, source: &PathBuf, destination: &PathBuf, file: &File) {
        for strategy in self.strategies.iter() {
            if strategy.can_handle(&file.file_type) {
                return strategy.handle(source, destination, file);
                let layout = self.layout.as_ref().unwrap();
                return strategy.handle(source, destination, file, layout);
            }
        }
    }


@@ 68,7 69,7 @@ pub trait FileHandlerStrategy {
    fn is(&self, path: &PathBuf) -> bool;
    fn identify(&self) -> FileType;
    fn can_handle(&self, file_type: &FileType) -> bool;
    fn handle(&self, source: &PathBuf, destination: &PathBuf, file: &File);
    fn handle(&self, source: &PathBuf, destination: &PathBuf, file: &File, layout: &String);
}

pub enum FileType {

M src/gemini_parser.rs => src/gemini_parser.rs +5 -1
@@ 7,7 7,11 @@ pub fn parse(source: &str) -> String {
    let mut current_line_type: Option<LineType> = None;

    for line in lines {
        let line_type = identify_line(&(line[..3]), is_preformatted);
        let mut line_type = LineType::Text;
        if line.len() > 2 {
            let end = line.char_indices().map(|(i, _)| i).nth(2).unwrap();
            line_type = identify_line(&(line[..end]), is_preformatted);
        }
        match line_type {
            LineType::PreformattedToggle => is_preformatted = !is_preformatted,
            _ => {

M src/main.rs => src/main.rs +0 -5
@@ 6,15 6,10 @@ use std::io::Result;
use std::env::current_dir;
use std::fs::{create_dir_all, remove_dir_all};

use crate::gemini_parser::parse;
use crate::file_finder::find_files;
use crate::file_handler::FileHandler;

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 source = current_dir()?;
    let source_name = source.file_name().unwrap().to_string_lossy();
    let parent = source.parent().unwrap();