The Dump Project

'Crafted' /s by Isaac Clayton

render

Created: Wednesday April 28, 2021
Last Edited: Friday April 30, 2021

↖ Back to src?


use std::{fs, path::PathBuf, io::Write, collections::HashSet};
use crate::{dump::{ExtMap, Env}, metadata::{Context, Metadata}, route::Route};

pub fn get_children(environment: &mut Env, route: &Route) -> (Option, Vec) {
    let mut index    = None;
    let mut children = vec![];
    let mut slugs    = HashSet::new();

    let paths = fs::read_dir(&route.path).unwrap();
    for raw_path in paths {
        let path = raw_path.unwrap().path().to_path_buf();
        let new_route = route.cd(path.file_name().unwrap().to_str().unwrap());

        if environment.ignores(&new_route.path) { continue; }
        if !slugs.insert(new_route.slug()) {
            eprintln!(
                "Multiple slugs of the name '{}'; first duplicate is: {}",
                new_route.slug(),
                new_route.path.display()
            );
            panic!();
        }

        if new_route.slug() != "index" {
            children.push(new_route.clone());
        } else {
            index = Some(new_route.clone());
        }
    }

    return (index, children);
}

pub fn render(
    parent:      Option,
    route:       &Route,
    extensions:  &mut ExtMap,
    output_path: PathBuf,
    for_rss:     &mut Vec,
) -> Metadata {
    println!("|  {}", route.route.join("/"));
    fs::create_dir_all(output_path.clone())
        .expect("Could not create parent dir");

    let (index, children) = get_children(&mut extensions.env, &route);
    let mut md_children = vec![];

    let metadata = Metadata::from_route(&route);
    for_rss.push(metadata.clone());

    for child in children.iter() {
        let md_child = if child.path.is_file() {
            render_file(
                Some(metadata.clone()),
                child,
                extensions,
                output_path.clone(),
                for_rss,
            )
        } else {
            render(
                Some(metadata.clone()),
                child,
                extensions,
                output_path.join(child.slug()),
                for_rss,
            )
        };
        md_children.push(md_child);
    }

    return render_index(
        parent,
        metadata,
        index,
        md_children,
        extensions,
        output_path,
    );
}

pub fn render_index(
    parent:      Option,
    route:       Metadata,
    maybe_index: Option,
    children:    Vec,
    extensions:  &mut ExtMap,
    output_path: PathBuf,
) -> Metadata {
    let (raw_content, ext) = if let Some(index) = maybe_index {
        let raw = fs::read(&index.path).unwrap();
        // do not write raw index
        (raw, index.ext())
    } else {
        (vec![], "none".to_string())
    };

    let context = Context::new(
        route.clone(),
        parent.clone(),
        children.clone(),
        raw_content,
    );

    let rendered = extensions.render(&ext, context, true);
    let mut render_out = fs::File::create(output_path.join("index.html"))
        .expect("Could not create output render file");
    write!(render_out, "{}", rendered)
        .expect("Could not write out rendered");

    return route;
}

pub fn render_file(
    parent:      Option,
    route:       &Route,
    extensions:  &ExtMap,
    output_path: PathBuf,
    for_rss:     &mut Vec,
) -> Metadata {
    println!("|> {}", route.route.join("/"));

    let raw_content = fs::read(&route.path).unwrap();
    let mut raw_out = fs::File::create(output_path.join(format!("{}", route.slug_with_ext())))
        .expect("Could not create output raw file");
    raw_out.write_all(&raw_content)
        .expect("Could not write out raw");

    let metadata = Metadata::from_route(&route);
    for_rss.push(metadata.clone());
    let context = Context::new(
        metadata.clone(),
        parent,
        vec![],
        raw_content,
    );

    let actual_out = output_path.join(route.slug());
    fs::create_dir_all(actual_out.clone())
        .expect("Could not create parent dir");

    let rendered = extensions.render(&route.ext(), context, false);
    let mut render_out = fs::File::create(actual_out.join("index.html"))
        .expect("Could not create output render file");
    write!(render_out, "{}", rendered)
        .expect("Could not write out rendered");

    return metadata;
}