//! # mycelial.technology //! //! _glyph's static site generator_ //! //! This is an opinionated, custom-built HTML splicer. It reads HTML templates, splices //! them into a base template and writes the output. //! //! Templates are expected at `./templates` and output is written to `./site`. The `./site` //! directory will be created if it doesn't exist. //! //! A base template is expected at `./templates/base.html`. It must contain two tags: //! `[[ title ]]` and `[[ content ]]`. //! //! The root index template is expected at `./templates/index.html`. All other templates are //! expected to be in sub-directories; for example: `./templates/plants/index.html` or //! `./templates/fungi/entomopathogens.html`. //! //! The splicer crawls the sub-directories of `./templates`, reads each HTML file, splices //! it into the `[[ content ]]` tag of the base HTML template and writes the output to the //! `./site` directory (preserving the sub-directory structure). The contents of the `

` //! element are spliced into the `[[ title ]]` tag of the base HTML template for each //! sub-directory template. //! use std::{error, fs, io, path::Path}; // define the path for the template directory const TEMPLATE_DIR: &str = "./templates"; // define the path for the generated site output const SITE_DIR: &str = "./site"; fn main() -> Result<(), Box> { // read the base html template to a string let base = format!("{}/base.html", TEMPLATE_DIR); let base_path = Path::new(&base); let base_html = fs::read_to_string(base_path) .expect("couldn't read from templates/base.html; does it exist?"); // read the index html template to a string let index = format!("{}/index.html", TEMPLATE_DIR); let index_path = Path::new(&index); let index_html = fs::read_to_string(index_path) .expect("couldn't read from templates/index.html; does it exist?"); // create site directory if it doesn't already exist let site_dir_path = Path::new(&SITE_DIR); if !site_dir_path.is_dir() { fs::create_dir(site_dir_path).expect("failed to create site output directory"); } // integrate the content from the index template into the base template let mut index_output = base_html.replace("[[ content ]]", &index_html); // set the page title index_output = index_output.replace("[[ title ]]", "mycelial technology"); let index_output_path = format!("{}/index.html", SITE_DIR); // write the generated index html to file fs::write(index_output_path, index_output.trim()) .expect("failed to write the root index.html file"); // walk the template directory and collect paths for all files and sub-directories let template_files = fs::read_dir(TEMPLATE_DIR)? .map(|res| res.map(|e| e.path())) .collect::, io::Error>>()?; // loop through each file and sub-directory for entry in template_files { if entry.is_dir() { // replicate templates sub-directory structure in site output directory let template_sub_dir_suffix = entry.strip_prefix(TEMPLATE_DIR)?; let site_sub_dir = Path::new(SITE_DIR).join(template_sub_dir_suffix); // create the sub-directory if it doesn't already exist if !site_sub_dir.is_dir() { fs::create_dir(site_sub_dir)?; } // read each file from the sub-diretory for file in fs::read_dir(entry)? { let file = file?; let file_path = file.path(); let file_html = fs::read_to_string(&file_path)?; // find the index of the h2 tag (represents the page title) let mut title_start = file_html.find("

").expect("

tag not found"); // increment the index to represent the start of the title text title_start += 4; // find the index of the h2 closing tag let title_end = file_html.find("

").expect("

tag not found"); // obtain the title text as a string slice let title = &file_html[title_start..title_end]; // integrate the content from the template into the base template let mut file_output = base_html.replace("[[ content ]]", &file_html); // integrate the title of the page into the file output file_output = file_output.replace("[[ title ]]", title); // define the path to which the output html file will be written let file_output_path = file_path.to_string_lossy(); // replace the template directory path with the site output path let output_path = file_output_path.replace(TEMPLATE_DIR, SITE_DIR); // trim whitespace from the end of the generated html and write to file fs::write(output_path, file_output.trim())? } } } Ok(()) }