You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

81 lines
2.5KB

  1. use std::collections::HashMap;
  2. use std::fs::{create_dir, remove_dir_all};
  3. use std::path::Path;
  4. use glob::glob;
  5. use tera::{Tera, Context};
  6. use config:: Config;
  7. use errors::{Result, ResultExt};
  8. use page::{Page, order_pages};
  9. use utils::create_file;
  10. pub fn build(config: Config) -> Result<()> {
  11. if Path::new("public").exists() {
  12. // Delete current `public` directory so we can start fresh
  13. remove_dir_all("public").chain_err(|| "Couldn't delete `public` directory")?;
  14. }
  15. let tera = Tera::new("layouts/**/*").chain_err(|| "Error parsing templates")?;
  16. // ok we got all the pages HTML, time to write them down to disk
  17. create_dir("public")?;
  18. let public = Path::new("public");
  19. let mut pages: Vec<Page> = vec![];
  20. let mut sections: HashMap<String, Vec<Page>> = HashMap::new();
  21. // First step: do all the articles and group article by sections
  22. // hardcoded pattern so can't error
  23. for entry in glob("content/**/*.md").unwrap().filter_map(|e| e.ok()) {
  24. let path = entry.as_path();
  25. let mut page = Page::from_file(&path)?;
  26. let mut current_path = public.clone().to_path_buf();
  27. for section in &page.sections {
  28. current_path.push(section);
  29. if !current_path.exists() {
  30. create_dir(&current_path)?;
  31. }
  32. let str_path = current_path.as_path().to_string_lossy().to_string();
  33. if sections.contains_key(&str_path) {
  34. sections.get_mut(&str_path).unwrap().push(page.clone());
  35. } else {
  36. sections.insert(str_path, vec![page.clone()]);
  37. }
  38. }
  39. current_path.push(&page.filename);
  40. create_dir(&current_path)?;
  41. create_file(current_path.join("index.html"), &page.render_html(&tera, &config)?)?;
  42. pages.push(page);
  43. }
  44. for (section, pages) in sections {
  45. render_section_index(section, pages, &tera, &config)?;
  46. }
  47. Ok(())
  48. }
  49. fn render_section_index(section: String, pages: Vec<Page>, tera: &Tera, config: &Config) -> Result<()> {
  50. let path = Path::new(&section);
  51. let mut context = Context::new();
  52. context.add("pages", &order_pages(pages));
  53. context.add("config", &config);
  54. let section_name = match path.components().into_iter().last() {
  55. Some(s) => s.as_ref().to_string_lossy().to_string(),
  56. None => bail!("Couldn't find a section name in {:?}", path.display())
  57. };
  58. create_file(path.join("index.html"), &tera.render(&format!("{}.html", section_name), context)?)
  59. }