From 1d75887bb7266a76223c68c517229bb6c869f403 Mon Sep 17 00:00:00 2001 From: glyph Date: Tue, 23 Nov 2021 20:35:34 +0200 Subject: [PATCH] separate application logic and introduce eprintln --- src/lib.rs | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 107 ++----------------------------------------------- 2 files changed, 117 insertions(+), 103 deletions(-) create mode 100644 src/lib.rs diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..e00467b --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,113 @@ +//! # nyf +//! +//! _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::{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"; + +pub fn run() -> Result<(), &'static str> { + // 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) + .map_err(|_| "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) + .map_err(|_| "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).map_err(|_| "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()) + .map_err(|_| "failed to write the root index.html file")?; + + // walk the template directory and collect paths for all files and sub-directories + let template_files: Vec<_> = fs::read_dir(TEMPLATE_DIR) + .map_err(|_| "failed to read template directory")? + .map(|res| res.map(|e| e.path())) + .collect::, io::Error>>() + .map_err(|_| "failed to collect template file paths")?; + + // 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) + .map_err(|_| "failed to strip prefix from template directory path")?; + 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) + .map_err(|_| "failed to create a site output sub-directory")?; + } + // read each file from the sub-directory + for file in fs::read_dir(entry) + .map_err(|_| "failed to enumerate template sub-directory files")? + { + let file = file.map_err(|_| "failed to obtain sub-directory file data")?; + let file_path = file.path(); + let file_html = fs::read_to_string(&file_path) + .map_err(|_| "failed to read template html file to string")?; + // find the index of the h2 tag (represents the page title) + let mut title_start = file_html.find("

").ok_or("

tag not found in html")?; + // 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("

") + .ok_or("

tag not found in html")?; + // 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()) + .map_err(|_| "failed to write html file to site directory")? + } + } + } + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index 20e58ef..3bae31a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,107 +1,8 @@ -//! # nyf -//! -//! _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::{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"; +use std::process; fn main() { - // 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: Vec<_> = fs::read_dir(TEMPLATE_DIR) - .expect("failed to read template directory") - .map(|res| res.map(|e| e.path())) - .collect::, io::Error>>() - .expect("failed to collect template file paths"); - - // 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) - .expect("failed to strip prefix from template directory path"); - 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).expect("failed to create a site output sub-directory"); - } - // read each file from the sub-diretory - for file in fs::read_dir(entry).expect("failed to read file in template sub-directory") - { - let file = file.unwrap(); - let file_path = file.path(); - let file_html = fs::read_to_string(&file_path) - .expect("failed to read template html file to string"); - // 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()) - .expect("failed to write html file to site directory") - } - } + if let Err(e) = nyf::run() { + eprintln!("error: {}", e); + process::exit(1); } }