diff --git a/.github/workflows/deploy-site.yml b/.github/workflows/deploy-site.yml index 6cf2ff1..303811d 100644 --- a/.github/workflows/deploy-site.yml +++ b/.github/workflows/deploy-site.yml @@ -18,10 +18,10 @@ jobs: run: sudo apt-get install cargo - name: Install simple-ssg - run: cargo install simple-ssg + run: cargo install --git https://github.com/ryanabx/simple-ssg - name: Generate static site - run: ~/.cargo/bin/simple-ssg --clean ./docs -o ./output -t github-markdown + run: ~/.cargo/bin/simple-ssg ./docs ./output - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@v4 diff --git a/Cargo.lock b/Cargo.lock index 5eae502..28d5400 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aho-corasick" @@ -191,12 +191,6 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" -[[package]] -name = "jotdown" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fff02adc563a0901266af314a47aa676f950a2f328a60b20691fdba0946fd98" - [[package]] name = "libc" version = "0.2.158" @@ -331,16 +325,14 @@ dependencies = [ [[package]] name = "simple-ssg" -version = "4.1.0" +version = "5.0.0" dependencies = [ "anyhow", "clap", "env_logger", - "jotdown", "log", "pulldown-cmark", "rand", - "thiserror", "walkdir", ] @@ -361,26 +353,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "thiserror" -version = "1.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "unicase" version = "2.7.0" diff --git a/Cargo.toml b/Cargo.toml index 4c76e77..f8c57be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,18 +5,16 @@ repository = "https://github.com/ryanabx/simple-ssg" website = "https://ryanabx.github.io/simple-ssg" license = "MIT" readme = "README.md" -version = "4.1.0" +version = "5.0.0" edition = "2021" -description = "Plain and simple static site generator for Djot and Markdown light markup languages" +description = "Simplest static site generator for Markdown" [dependencies] anyhow = "1.0.86" clap = { version = "4.5.16", features = ["derive"] } env_logger = "0.11.5" -jotdown = "0.5.0" log = "0.4.22" pulldown-cmark = "0.12.1" -thiserror = "1.0.63" walkdir = "2.5.0" [dev-dependencies] diff --git a/README.md b/README.md index 97134d8..dec8e74 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -# SMPL Static Site Generator - Generate a website with the lowest effort! +# Simple Static Site Generator - Generate a website with the lowest effort! ## Usage ```shell -cargo install simple-ssg +cargo install --git https://github.com/ryanabx/simple-ssg -simple-ssg -o [OUTPUT_DIRECTORY] +simple-ssg ``` ## Support Goals @@ -14,5 +14,4 @@ This static site generator aims to support: - [x] Plaintext HTML - [x] Linking to pages within static site -- [x] Image resources -- [x] Templates (must be named template.html) \ No newline at end of file +- [x] Miscellaneous resources in your site \ No newline at end of file diff --git a/src/errors.rs b/src/errors.rs deleted file mode 100644 index 1c589ff..0000000 --- a/src/errors.rs +++ /dev/null @@ -1,15 +0,0 @@ -use std::path::PathBuf; - -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum SsgError { - #[error("index.{{dj|djot}} not found! consider creating one in the base target directory as the default page.")] - IndexPageNotFound, - #[error("Path {0} is not relative to target directory")] - PathNotRelative(PathBuf), - #[error("An entry returned error {0}")] - DirEntryError(walkdir::Error), - #[error("Referenced file path {0} does not exist!")] - LinkError(PathBuf), -} diff --git a/src/main.rs b/src/main.rs index 67e0e26..0246be2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,149 +1,35 @@ -use anyhow::anyhow; -use errors::SsgError; -use jotdown::{Container, Event}; use pulldown_cmark::{CowStr, Options}; use std::{ - env, fs::{self, read_dir}, path::{Path, PathBuf}, }; -use templates::BuiltInTemplate; use walkdir::WalkDir; use clap::Parser; - -mod errors; -mod templates; #[cfg(test)] mod tests; -mod utils; - -mod markdown; -/// Djot static site generator +/// Simple static site generator #[derive(Parser, Debug)] #[command(version, about, long_about = None)] struct ConsoleArgs { - /// Path to the directory to use to generate the site (not required if -f is specified) - directory: Option, - /// Process a single file instead of a directory - #[arg(short, conflicts_with = "clean", conflicts_with = "output_path")] - file: Option, - /// Optional output path override. Defaults to ./output for directories - #[arg(short, conflicts_with = "file")] - output_path: Option, - /// Clean the output directory before generating the site. Useful for multiple runs - #[arg(long, conflicts_with = "file")] - clean: bool, - /// Specify the website prefix (defaults to local paths i.e. `./`) - #[arg(long)] - web_prefix: Option, - /// Specify a built in template to use (will override a template.html - /// in any directory!). defaults to whatever templates are found in template.html in the - /// directories. - #[arg(short, long)] - template: Option, - /// Try the legacy method of generating a static site - #[arg(long)] - legacy: bool, + /// Path to the directory to use to generate the site + directory: PathBuf, + /// Path of the base output directory + output_path: PathBuf, + /// Optional web prefix + prefix: Option, } fn main() -> anyhow::Result<()> { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("warn")).init(); log::trace!("Begin simple-ssg::main()"); let args = ConsoleArgs::parse(); - if args.legacy { - run_program(args) - } else { - run_program_2(args) - } -} - -fn run_program_2(args: ConsoleArgs) -> anyhow::Result<()> { - if args.directory.is_none() - || args.file.is_some() - || args.template.is_some() - || args.output_path.is_none() - { - log::error!("Args incorrect"); - anyhow::bail!("Args incorrect"); - } - generate_site_2( - &args.directory.unwrap(), - &args.output_path.unwrap(), - args.web_prefix.as_deref(), - )?; - Ok(()) -} - -fn run_program(args: ConsoleArgs) -> anyhow::Result<()> { - let (target_path, output_path) = if args.directory.is_some() && args.file.is_some() { - return Err(anyhow!( - "Cannot specify both a directory and a path! (Specified {} and -f {})", - args.directory.unwrap().display(), - args.file.unwrap().display() - )); - } else if let Some(dir) = args.directory { - if dir.is_file() { - return Err(anyhow!( - "Path {} is a file. Specify -f if this was intended.", - dir.display() - )); - } - ( - dir, - args.output_path - .unwrap_or(env::current_dir()?.join("output")), - ) - } else if let Some(path) = args.file { - if path.is_dir() { - return Err(anyhow!("Path {} is a directory. Specify without the -f positional argument if this was intended.", path.display())); - } - (path.clone(), path.parent().unwrap().to_path_buf()) - } else { - return Err(anyhow!( - "Must specify either a directory or a path with -f " - )); - }; - // Clean the output directory if clean is specified - if args.clean { - log::debug!( - "Clean argument specified, cleaning output path {:?}...", - &output_path - ); - if let Err(_) = std::fs::remove_dir_all(&output_path) { - log::trace!("Nothing to clean!"); - } else { - log::trace!("Clean successful!"); - } - } - generate_site( - &target_path, - &output_path, - args.web_prefix.as_deref(), - args.template, - )?; + generate(&args.directory, &args.output_path, args.prefix.as_deref())?; Ok(()) } -#[derive(Clone, Debug)] -pub enum FirstPassResult { - Dir { - depth: usize, - relative_path: PathBuf, - }, - HtmlOutput { - depth: usize, - html: String, - relative_path: PathBuf, - }, -} - -fn generate_site_2( - root_dir: &Path, - output_dir: &Path, - web_prefix: Option<&str>, -) -> anyhow::Result<()> { +fn generate(root_dir: &Path, output_dir: &Path, web_prefix: Option<&str>) -> anyhow::Result<()> { let root_dir = root_dir.canonicalize()?; let _ = fs::create_dir_all(&output_dir); let output_dir = output_dir.canonicalize()?; @@ -163,7 +49,7 @@ fn generate_site_2( } directory_index.push_str(&create_directory_index(x_path)?); log::info!("{}", &directory_index); - let html = markdown::md_to_html(&directory_index, x_path, web_prefix)?; + let html = md_to_html(&directory_index, x_path, web_prefix)?; let result_path = output_dir.join(x_path.join("index.html").strip_prefix(&root_dir)?); log::info!("Result path: {:?}", &result_path); @@ -178,7 +64,7 @@ fn generate_site_2( output_dir.join(x_path.with_extension("html").strip_prefix(&root_dir)?); if x_path.extension().is_some_and(|ext| ext == "md") { let md = fs::read_to_string(x_path)?; - let html = markdown::md_to_html(&md, x_path.parent().unwrap(), web_prefix)?; + let html = md_to_html(&md, x_path.parent().unwrap(), web_prefix)?; let _ = std::fs::create_dir_all(result_path.parent().unwrap()); if let Err(e) = std::fs::write(&result_path, html.as_bytes()) { log::error!("Could not write file to path {:?}: {}", &result_path, e); @@ -187,7 +73,12 @@ fn generate_site_2( } else { let _ = std::fs::create_dir_all(result_path.parent().unwrap()); if let Err(e) = std::fs::copy(x_path, &result_path) { - log::error!("Could not copy file from {:?} to {:?}: {}", x_path, &result_path, e); + log::error!( + "Could not copy file from {:?} to {:?}: {}", + x_path, + &result_path, + e + ); anyhow::bail!(e); } } @@ -230,162 +121,16 @@ fn directory_string(root_path: &Path, target_path: &Path, name: &str) -> String ) } -fn generate_site( - target_path: &Path, - output_path: &Path, - web_prefix: Option<&str>, - template: Option, -) -> anyhow::Result<()> { - let _ = std::fs::create_dir_all(output_path); - log::trace!( - "Created output directory {:?} if it didn't exist...", - output_path - ); - - let mut first_pass_results = Vec::new(); - - log::info!("1/3: Site generation and indexing..."); - if target_path.is_dir() && output_path.is_dir() { - if !utils::check_has_index(target_path) { - log::warn!("{}", SsgError::IndexPageNotFound); - } - for entry in WalkDir::new(target_path) { - match entry { - Ok(direntry) => process_path( - direntry.path(), - target_path, - output_path, - &template, - web_prefix, - direntry.depth(), - &mut first_pass_results, - )?, - Err(e) => { - log::warn!("{}", SsgError::DirEntryError(e)); - } - } - } - } else if target_path.is_file() { - process_path( - target_path, - target_path.parent().unwrap(), - output_path, - &template, - web_prefix, - 1, - &mut first_pass_results, - )?; - } else { - return Err(anyhow!( - "Target path {} is not a file or a directory.", - target_path.display() - )); - } - - // Validation pass - log::info!("2/3: Generating additional site content (if necessary) and saving..."); - - for result in first_pass_results.clone() { - match result { - FirstPassResult::Dir { .. } => continue, - FirstPassResult::HtmlOutput { - depth, - html, - relative_path, - } => { - let table_of_contents = generate_table_of_contents( - &first_pass_results, - depth, - &relative_path, - web_prefix, - ); - let text = html.replace("", &table_of_contents); - let result_path = output_path.join(&relative_path); - log::debug!("{:?} :: {:?}", &result_path, &relative_path); - std::fs::write(&result_path, text.as_bytes())?; - } - } - // Generate the table of contents - } - - log::info!("3/3: Done!"); - - Ok(()) -} - -fn process_path( - entity: &Path, - target_path: &Path, - output_path: &Path, - template: &Option, - web_prefix: Option<&str>, - depth: usize, - first_pass_results: &mut Vec, -) -> anyhow::Result<()> { - let relative = match entity.strip_prefix(target_path) { - Ok(relative) => relative.to_path_buf(), - Err(_) => { - log::warn!("{}", SsgError::PathNotRelative(entity.to_path_buf())); - return Ok(()); - } - }; - log::debug!("{:?} :: {}", &relative, depth); - if entity.is_dir() { - log::trace!("Path {:?} is a directory, continuing...", entity); - first_pass_results.push(FirstPassResult::Dir { - depth, - relative_path: relative, - }); - return Ok(()); - } else if entity.ends_with("template.html") { - log::trace!("Path {:?} is a template, continuing...", entity); - return Ok(()); - } - log::trace!("Path: {:?}", entity); - let new_path = output_path.join(&relative); - let _ = std::fs::create_dir_all(new_path.parent().unwrap()); - match entity.extension().map(|x| x.to_str().unwrap()) { - Some("dj") | Some("djot") | Some("md") => { - let html_template = template.clone().map_or( - utils::get_template_if_exists(entity, target_path)?, - |template| Some(template.get_template()), - ); - let result_path = new_path.with_extension("html"); - log::debug!( - "Generating .html from {:?} and moving to {:?}", - entity, - &result_path - ); - let input_str = std::fs::read_to_string(entity)?; - let html = match entity.extension().map(|x| x.to_str().unwrap()) { - Some("md") => process_markdown(&input_str, entity.parent().unwrap(), web_prefix)?, - Some("dj") | Some("djot") => { - process_djot(&input_str, entity.parent().unwrap(), web_prefix)? - } - _ => unreachable!(), - }; - let html_formatted = utils::wrap_html_content(&html, html_template.as_deref()); - first_pass_results.push(FirstPassResult::HtmlOutput { - depth: depth, - html: html_formatted, - relative_path: relative.with_extension("html"), - }); - } - _ => { - std::fs::copy(entity, &new_path)?; - } - } - Ok(()) -} - -fn process_markdown( - markdown_input: &str, +/// Take markdown input, and change links if necessary +pub fn md_to_html( + markdown: &str, file_parent_dir: &Path, web_prefix: Option<&str>, ) -> anyhow::Result { + log::info!("Markdown to html: {:?}", file_parent_dir); let mut options = Options::empty(); options.insert(Options::ENABLE_GFM); - let events = pulldown_cmark::Parser::new_ext(markdown_input, options) + let events = pulldown_cmark::Parser::new_ext(markdown, options) .map(|event| -> anyhow::Result { match event { pulldown_cmark::Event::Start(pulldown_cmark::Tag::Link { @@ -396,24 +141,34 @@ fn process_markdown( }) => { let inner = dest_url.to_string(); let referenced_path = file_parent_dir.join(&inner); - if referenced_path - .extension() - .is_some_and(|ext| ext == "dj" || ext == "djot" || ext == "md") - { + if referenced_path.extension().is_some_and(|ext| ext == "md") { let new_path = Path::new(&inner).with_extension("html"); + log::info!("Path: {:?} -> {:?}", &inner, &new_path); if !referenced_path.exists() { - log::warn!("{}", SsgError::LinkError(referenced_path)) - } - let dest_url = CowStr::Boxed( - format!("{}{}", web_prefix.unwrap_or(""), new_path.to_string_lossy()) + log::warn!("Path {:?} doesn't exist!", referenced_path); + Ok(pulldown_cmark::Event::Start(pulldown_cmark::Tag::Link { + link_type, + dest_url, + title, + id, + })) + } else { + // Create destination url + let dest_url = CowStr::Boxed( + format!( + "{}{}", + web_prefix.unwrap_or(""), + new_path.to_string_lossy() + ) .into_boxed_str(), - ); - Ok(pulldown_cmark::Event::Start(pulldown_cmark::Tag::Link { - link_type, - dest_url, - title, - id, - })) + ); + Ok(pulldown_cmark::Event::Start(pulldown_cmark::Tag::Link { + link_type, + dest_url, + title, + id, + })) + } } else { Ok(pulldown_cmark::Event::Start(pulldown_cmark::Tag::Link { link_type, @@ -427,190 +182,8 @@ fn process_markdown( } }) .collect::, _>>()?; - + log::info!("Done"); let mut html = String::new(); pulldown_cmark::html::push_html(&mut html, events.iter().cloned()); Ok(html) } - -fn process_djot( - djot_input: &str, - file_parent_dir: &Path, - web_prefix: Option<&str>, -) -> anyhow::Result { - let events = jotdown::Parser::new(djot_input) - .map(|event| -> anyhow::Result { - match event { - Event::Start(Container::Link(text, link_type), attributes) => { - let inner = text.to_string(); - let referenced_path = file_parent_dir.join(&inner); - if referenced_path - .extension() - .is_some_and(|ext| ext == "dj" || ext == "djot" || ext == "md") - { - let new_path = Path::new(&inner).with_extension("html"); - if referenced_path.exists() { - Ok(Event::Start( - Container::Link( - std::borrow::Cow::Owned(format!( - "{}{}", - web_prefix.unwrap_or(""), - new_path.to_string_lossy() - )), - link_type, - ), - attributes, - )) - } else { - log::warn!("{}", SsgError::LinkError(referenced_path)); - Ok(Event::Start(Container::Link(text, link_type), attributes)) - } - } else { - Ok(Event::Start(Container::Link(text, link_type), attributes)) - } - } - Event::End(Container::Link(text, link_type)) => { - let inner = text.to_string(); - let referenced_path = file_parent_dir.join(&inner); - if referenced_path - .extension() - .is_some_and(|ext| ext == "dj" || ext == "djot" || ext == "md") - { - let new_path = Path::new(&inner).with_extension("html"); - if referenced_path.exists() { - Ok(Event::End(Container::Link( - std::borrow::Cow::Owned(format!( - "{}{}", - web_prefix.unwrap_or(""), - new_path.to_string_lossy() - )), - link_type, - ))) - } else { - Ok(Event::End(Container::Link(text, link_type))) - } - } else { - Ok(Event::End(Container::Link(text, link_type))) - } - } - _ => Ok(event), - } - }) - .collect::, _>>()?; - let html = jotdown::html::render_to_string(events.iter().cloned()); - Ok(html) -} - -fn generate_table_of_contents( - results: &Vec, - my_depth: usize, - my_result: &Path, - web_prefix: Option<&str>, -) -> String { - let mut table_of_contents_html = "
    ".to_string(); - log::debug!("
      "); - let mut prev_depth = 0; - let mut prev_file_depth = 0; - let mut prev_folders = Vec::new(); - for result in results { - match result { - FirstPassResult::Dir { - depth, - relative_path, - } => { - log::trace!("Dir: {}", &relative_path.to_string_lossy()); - let mut depth_diff = *depth as i32 - prev_depth as i32; - while depth_diff < 0 { - if prev_folders.pop().is_none() { - let format_string = format!("
    "); - log::debug!("{} (Dir, depth_diff={})", &format_string, depth_diff); - table_of_contents_html.push_str(&format_string); - } - depth_diff += 1; - } - prev_depth = *depth; - if *depth > 0 { - log::trace!( - "Adding {} to the folders stack (at depth {})", - &relative_path.to_string_lossy(), - *depth - ); - prev_folders.push( - relative_path - .file_name() - .unwrap() - .to_string_lossy() - .to_string(), - ); - } - } - FirstPassResult::HtmlOutput { - relative_path, - depth, - .. - } => { - log::trace!("File: {}", &relative_path.to_string_lossy()); - let mut depth_diff = *depth as i32 - prev_depth as i32; - while depth_diff < 0 { - if prev_folders.pop().is_none() { - let format_string = format!("
"); - log::debug!("{} (File, depth_diff={})", &format_string, depth_diff); - table_of_contents_html.push_str(&format_string); - } - depth_diff += 1; - } - let mut pos_depth_diff = prev_folders.len(); - while pos_depth_diff > 0 { - let folder_name = prev_folders.remove(0); - let format_string = format!("
  • {}:
  • ", &folder_name,); - log::debug!( - "{} (folder, depth={})", - &format_string, - (*depth - pos_depth_diff) - ); - table_of_contents_html.push_str(&format_string); - let format_string = format!("
      "); - log::debug!("{}, prev_folders-={}", &format_string, &folder_name); - table_of_contents_html.push_str(&format_string); - pos_depth_diff -= 1; - } - prev_depth = *depth; - prev_file_depth = *depth; - if relative_path == my_result { - let format_string = format!( - "
    • {}
    • ", - &relative_path.file_stem().unwrap().to_string_lossy() - ); - log::debug!("{} (file, depth={})", &format_string, *depth); - table_of_contents_html.push_str(&format_string); - } else { - let format_string = format!( - "
    • {}
    • ", - if my_depth > 1 { - "../".repeat(my_depth - 1) - } else { - "".to_string() - }, - &web_prefix.unwrap_or(""), // "./" if "" doesn't work - &relative_path.to_string_lossy(), - &relative_path.file_stem().unwrap().to_string_lossy() - ); - log::debug!("{} (file, depth={})", &format_string, *depth); - table_of_contents_html.push_str(&format_string); - } - } - } - } - prev_depth -= prev_folders.len(); - log::trace!("prev_depth - {} = {}", prev_folders.len(), prev_depth); - log::trace!("prev_file_depth = {}", prev_file_depth); - let mut depth_diff = 0 - prev_file_depth as i32; - while depth_diff < 0 { - let format_string = format!("
    "); - log::debug!("{} (end, depth_diff={})", &format_string, depth_diff); - table_of_contents_html.push_str(&format_string); - depth_diff += 1; - } - // log::debug!("Table of contents: {}", &table_of_contents_html); - table_of_contents_html -} diff --git a/src/markdown.rs b/src/markdown.rs deleted file mode 100644 index ebc4f01..0000000 --- a/src/markdown.rs +++ /dev/null @@ -1,71 +0,0 @@ -use std::path::Path; - -use pulldown_cmark::{CowStr, Options}; - - -/// Take markdown input, and change links if necessary -pub fn md_to_html( - markdown: &str, - file_parent_dir: &Path, - web_prefix: Option<&str>, -) -> anyhow::Result { - log::info!("Markdown to html: {:?}", file_parent_dir); - let mut options = Options::empty(); - options.insert(Options::ENABLE_GFM); - let events = pulldown_cmark::Parser::new_ext(markdown, options) - .map(|event| -> anyhow::Result { - match event { - pulldown_cmark::Event::Start(pulldown_cmark::Tag::Link { - link_type, - dest_url, - title, - id, - }) => { - let inner = dest_url.to_string(); - let referenced_path = file_parent_dir.join(&inner); - if referenced_path - .extension() - .is_some_and(|ext| ext == "md") - { - let new_path = Path::new(&inner).with_extension("html"); - log::info!("Path: {:?} -> {:?}", &inner, &new_path); - if !referenced_path.exists() { - log::warn!("Path {:?} doesn't exist!", referenced_path); - Ok(pulldown_cmark::Event::Start(pulldown_cmark::Tag::Link { - link_type, - dest_url, - title, - id, - })) - } - else { - // Create destination url - let dest_url = CowStr::Boxed( - format!("{}{}", web_prefix.unwrap_or(""), new_path.to_string_lossy()) - .into_boxed_str(), - ); - Ok(pulldown_cmark::Event::Start(pulldown_cmark::Tag::Link { - link_type, - dest_url, - title, - id, - })) - } - } else { - Ok(pulldown_cmark::Event::Start(pulldown_cmark::Tag::Link { - link_type, - dest_url, - title, - id, - })) - } - } - _ => Ok(event), - } - }) - .collect::, _>>()?; - log::info!("Done"); - let mut html = String::new(); - pulldown_cmark::html::push_html(&mut html, events.iter().cloned()); - Ok(html) -} \ No newline at end of file diff --git a/src/templates.rs b/src/templates.rs deleted file mode 100644 index f4e9944..0000000 --- a/src/templates.rs +++ /dev/null @@ -1,1311 +0,0 @@ -use clap::ValueEnum; - -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] -pub enum BuiltInTemplate { - GithubMarkdown, - ForceNone, -} - -impl BuiltInTemplate { - pub fn get_template(&self) -> String { - match self { - Self::ForceNone => { - "".to_string() - } - Self::GithubMarkdown => { - r##" - - - - - - - - -
    -
    - Contents: - -
    -
    -
    - -
    -
    -
    - - - "##.to_string() - } - } - } -} diff --git a/src/tests.rs b/src/tests.rs index cd2d681..8ba1878 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -7,136 +7,136 @@ use std::{ use rand::{distributions::Alphanumeric, Rng}; -use crate::{errors::SsgError, ConsoleArgs}; +// TODO: Remake tests -#[test] -fn site_with_links() -> anyhow::Result<()> { - let _ = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")) - .try_init(); - let temp_dir = temp_dir().join(temp_dir_name()); - let res = panic::catch_unwind(|| { - { - (|| { - log::trace!("Creating nested directories"); - create_dir_all(&temp_dir.join("target/nested2"))?; - create_dir_all(&temp_dir.join("target/nested3"))?; - log::trace!("Done"); - let mut djot_file_1 = File::create(&temp_dir.join("target/index.dj"))?; - write!( - djot_file_1, - "# Hey everyone!\n\nThis is an example djot file!\n\n> Hey what's up. Link:\n\n[HIHIDHI](nested2/hey.dj)" - )?; - log::trace!("Flushing file 1"); - djot_file_1.flush()?; - log::trace!("Done"); - let mut djot_file_2 = File::create(&temp_dir.join("target/nested2/hey.dj"))?; - write!(djot_file_2, "File 2\n\n### Hey\n\n[link](../index.dj)")?; - log::trace!("Flushing file 2"); - djot_file_2.flush()?; - log::trace!("Done"); - let mut djot_file_3 = File::create(&temp_dir.join("target/nested3/third_file.dj"))?; - write!( - djot_file_3, - "File 3\n\n### What's good in the hous\n\n[link](../nested2/hey.dj)" - )?; - log::trace!("Flushing file 3"); - djot_file_3.flush()?; - log::trace!("Djot files written"); - let args = ConsoleArgs { - directory: Some(temp_dir.join("target")), - file: None, - output_path: Some(temp_dir.join("output")), - clean: false, - web_prefix: None, - template: Some(crate::templates::BuiltInTemplate::ForceNone), - legacy: true - }; - log::trace!("Running program"); - crate::run_program(args)?; - assert!(temp_dir.join("output/index.html").exists()); - assert!(!temp_dir.join("output/index.dj").exists()); - assert!(temp_dir.join("output/nested2/hey.html").exists()); - assert!(!temp_dir.join("output/nested2/hey.dj").exists()); - assert!(temp_dir.join("output/nested3/third_file.html").exists()); - assert!(!temp_dir.join("output/nested3/third_file.dj").exists()); - Ok(()) - })() - } - }); +// #[test] +// fn site_with_links() -> anyhow::Result<()> { +// let _ = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")) +// .try_init(); +// let temp_dir = temp_dir().join(temp_dir_name()); +// let res = panic::catch_unwind(|| { +// { +// (|| { +// log::trace!("Creating nested directories"); +// create_dir_all(&temp_dir.join("target/nested2"))?; +// create_dir_all(&temp_dir.join("target/nested3"))?; +// log::trace!("Done"); +// let mut djot_file_1 = File::create(&temp_dir.join("target/index.dj"))?; +// write!( +// djot_file_1, +// "# Hey everyone!\n\nThis is an example djot file!\n\n> Hey what's up. Link:\n\n[HIHIDHI](nested2/hey.dj)" +// )?; +// log::trace!("Flushing file 1"); +// djot_file_1.flush()?; +// log::trace!("Done"); +// let mut djot_file_2 = File::create(&temp_dir.join("target/nested2/hey.dj"))?; +// write!(djot_file_2, "File 2\n\n### Hey\n\n[link](../index.dj)")?; +// log::trace!("Flushing file 2"); +// djot_file_2.flush()?; +// log::trace!("Done"); +// let mut djot_file_3 = File::create(&temp_dir.join("target/nested3/third_file.dj"))?; +// write!( +// djot_file_3, +// "File 3\n\n### What's good in the hous\n\n[link](../nested2/hey.dj)" +// )?; +// log::trace!("Flushing file 3"); +// djot_file_3.flush()?; +// log::trace!("Djot files written"); +// let args = ConsoleArgs { +// directory: Some(temp_dir.join("target")), +// file: None, +// output_path: Some(temp_dir.join("output")), +// clean: false, +// web_prefix: None, +// template: Some(crate::templates::BuiltInTemplate::ForceNone), +// legacy: true +// }; +// log::trace!("Running program"); +// crate::run_program(args)?; +// assert!(temp_dir.join("output/index.html").exists()); +// assert!(!temp_dir.join("output/index.dj").exists()); +// assert!(temp_dir.join("output/nested2/hey.html").exists()); +// assert!(!temp_dir.join("output/nested2/hey.dj").exists()); +// assert!(temp_dir.join("output/nested3/third_file.html").exists()); +// assert!(!temp_dir.join("output/nested3/third_file.dj").exists()); +// Ok(()) +// })() +// } +// }); - log::trace!("Done with testing"); +// log::trace!("Done with testing"); - let _ = remove_dir_all(&temp_dir); - match res { - Ok(e) => e, - _ => Err(anyhow::anyhow!("Panic occurred")), - } -} +// let _ = remove_dir_all(&temp_dir); +// match res { +// Ok(e) => e, +// _ => Err(anyhow::anyhow!("Panic occurred")), +// } +// } -#[test] -fn site_warn_without_index() -> anyhow::Result<()> { - let _ = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")) - .try_init(); - let temp_dir = temp_dir().join(temp_dir_name()); - // Perform test with catch - let res = panic::catch_unwind(|| { - { - (|| -> anyhow::Result<()> { - create_dir_all(&temp_dir.join("target/nested"))?; - let mut djot_file_1 = File::create(&temp_dir.join("target/nested/example.dj"))?; - write!( - djot_file_1, - "# Hey everyone!\n\nThis is an example djot file!\n\n> Hey what's up" - )?; - djot_file_1.flush()?; +// #[test] +// fn site_warn_without_index() -> anyhow::Result<()> { +// let _ = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")) +// .try_init(); +// let temp_dir = temp_dir().join(temp_dir_name()); +// // Perform test with catch +// let res = panic::catch_unwind(|| { +// { +// (|| -> anyhow::Result<()> { +// create_dir_all(&temp_dir.join("target/nested"))?; +// let mut djot_file_1 = File::create(&temp_dir.join("target/nested/example.dj"))?; +// write!( +// djot_file_1, +// "# Hey everyone!\n\nThis is an example djot file!\n\n> Hey what's up" +// )?; +// djot_file_1.flush()?; - let mut djot_file_2 = File::create(&temp_dir.join("target/example2.dj"))?; - write!( - djot_file_2, - "# Hey everyone!\n\nThis is another example djot file!\n\n> Hey what's up!!" - )?; - djot_file_2.flush()?; +// let mut djot_file_2 = File::create(&temp_dir.join("target/example2.dj"))?; +// write!( +// djot_file_2, +// "# Hey everyone!\n\nThis is another example djot file!\n\n> Hey what's up!!" +// )?; +// djot_file_2.flush()?; - let args = ConsoleArgs { - directory: Some(temp_dir.join("target")), - output_path: Some(temp_dir.join("output")), - clean: false, - web_prefix: None, - template: Some(crate::templates::BuiltInTemplate::ForceNone), - file: None, - legacy: true, - }; - crate::run_program(args)?; - Ok(()) - })() - } - }); +// let args = ConsoleArgs { +// directory: Some(temp_dir.join("target")), +// output_path: Some(temp_dir.join("output")), +// clean: false, +// web_prefix: None, +// template: Some(crate::templates::BuiltInTemplate::ForceNone), +// file: None, +// legacy: true, +// }; +// crate::run_program(args)?; +// Ok(()) +// })() +// } +// }); - let _ = remove_dir_all(&temp_dir); - match res { - Ok(e) => { - match e { - Ok(()) => { - // This should have errored out - Err(anyhow::anyhow!("This should have errored out")) - } - Err(e2) => match e2.downcast_ref::() { - Some(SsgError::IndexPageNotFound) => Ok(()), - _ => Err(e2), - }, - } - } - _ => Err(anyhow::anyhow!("Panic occurred")), - } -} +// let _ = remove_dir_all(&temp_dir); +// match res { +// Ok(e) => { +// match e { +// Ok(()) => { +// // This should have errored out +// Err(anyhow::anyhow!("This should have errored out")) +// } +// Err(e2) => match e2.downcast_ref::() { +// Some(SsgError::IndexPageNotFound) => Ok(()), +// _ => Err(e2), +// }, +// } +// } +// _ => Err(anyhow::anyhow!("Panic occurred")), +// } +// } -fn temp_dir_name() -> String { - format!( - ".simple-ssg-test-{}", - rand::thread_rng() - .sample_iter(&Alphanumeric) - .take(6) - .map(char::from) - .collect::() - ) -} +// fn temp_dir_name() -> String { +// format!( +// ".simple-ssg-test-{}", +// rand::thread_rng() +// .sample_iter(&Alphanumeric) +// .take(6) +// .map(char::from) +// .collect::() +// ) +// } diff --git a/src/utils.rs b/src/utils.rs deleted file mode 100644 index 8451cba..0000000 --- a/src/utils.rs +++ /dev/null @@ -1,52 +0,0 @@ -use std::{ - fs::read_to_string, - path::{Path, PathBuf}, -}; - -pub fn check_has_index(target_path: &Path) -> bool { - target_path.join("index.dj").exists() - || target_path.join("index.djot").exists() - || target_path.join("index.md").exists() -} - -pub fn get_template_if_exists( - djot_document_path: &Path, - root_path: &Path, -) -> anyhow::Result> { - if !is_ancestor(root_path, djot_document_path) { - Err(anyhow::anyhow!("Root path is not an ancestor of main path")) - } else { - let mut current = PathBuf::from(djot_document_path.parent().unwrap()); - loop { - let template_file = current.join("template.html"); - log::trace!("Checking for template file at {:?}", &template_file); - if template_file.exists() { - return Ok(Some(read_to_string(&template_file)?)); - } - if current == root_path { - break; - } - current = current.parent().unwrap().to_path_buf(); - } - Ok(None) - } -} - -/// Checks if `ancestor` is an ancestor of `descendant`. -fn is_ancestor(ancestor: &Path, descendant: &Path) -> bool { - let mut current = PathBuf::from(descendant); - while let Some(parent) = current.parent() { - if parent == ancestor { - return true; - } - current = parent.to_path_buf(); - } - false -} - -pub fn wrap_html_content(content: &str, template: Option<&str>) -> String { - match template { - Some(tmpl) => tmpl.to_string().replace("", content), - None => content.to_string(), - } -}