diff --git a/src/cmd/build.rs b/src/cmd/build.rs index 58621a8..e227208 100644 --- a/src/cmd/build.rs +++ b/src/cmd/build.rs @@ -50,7 +50,11 @@ pub fn build(config: Config) -> Result<()> { } - current_path.push(&page.filename); + if page.slug != "" { + current_path.push(&page.slug); + } else { + current_path.push(&page.url); + } create_dir(¤t_path)?; create_file(current_path.join("index.html"), &page.render_html(&tera, &config)?)?; pages.push(page); @@ -60,6 +64,12 @@ pub fn build(config: Config) -> Result<()> { render_section_index(section, pages, &tera, &config)?; } + // and now the index page + let mut context = Context::new(); + context.add("pages", &order_pages(pages)); + context.add("config", &config); + create_file(public.join("index.html"), &tera.render("index.html", context)?)?; + Ok(()) } diff --git a/src/front_matter.rs b/src/front_matter.rs index 3f63f67..2528546 100644 --- a/src/front_matter.rs +++ b/src/front_matter.rs @@ -44,7 +44,7 @@ pub fn parse_front_matter(front_matter: &str, page: &mut Page) -> Result<()> { } else if key == "slug" { page.slug = s.to_string(); } else if key == "url" { - page.url = Some(s.to_string()); + page.url = s.to_string(); } else if key == "category" { page.category = Some(s.to_string()); } else if key == "layout" { @@ -86,8 +86,8 @@ pub fn parse_front_matter(front_matter: &str, page: &mut Page) -> Result<()> { bail!("Errors parsing front matter: {:?}", parser.errors); } - if page.title == "" || page.slug == "" { - bail!("Front matter is missing required fields (title, slug or both)"); + if page.title == "" || (page.slug == "" && page.url == "") { + bail!("Front matter is missing required fields (title, slug/url or both)"); } Ok(()) @@ -149,7 +149,19 @@ authors = ["Bob", "Alice"]"#; } #[test] - fn test_ignores_pages_with_empty_front_matter() { + fn test_is_ok_with_url_instead_of_slug() { + let content = r#" +title = "Hello" +url = "hello-world""#; + let mut page = Page::default(); + let res = parse_front_matter(content, &mut page); + assert!(res.is_ok()); + assert_eq!(page.slug, "".to_string()); + assert_eq!(page.url, "hello-world".to_string()); + } + + #[test] + fn test_errors_with_empty_front_matter() { let content = r#" "#; let mut page = Page::default(); let res = parse_front_matter(content, &mut page); diff --git a/src/page.rs b/src/page.rs index a7f5752..5153d2f 100644 --- a/src/page.rs +++ b/src/page.rs @@ -41,6 +41,9 @@ pub struct Page { pub title: String, // The page slug pub slug: String, + // the url the page appears at, overrides the slug if set in the frontmatter + // otherwise is set after parsing front matter and sections + pub url: String, // the HTML rendered of the page pub content: String, @@ -52,8 +55,6 @@ pub struct Page { // it will be passed to the template context pub extra: HashMap, - // the url the page appears at, overrides the slug if set - pub url: Option, // only one category allowed pub category: Option, // optional date if we want to order pages (ie blog post) @@ -75,13 +76,13 @@ impl Default for Page { title: "".to_string(), slug: "".to_string(), + url: "".to_string(), raw_content: "".to_string(), content: "".to_string(), tags: vec![], is_draft: false, extra: HashMap::new(), - url: None, category: None, date: None, layout: None, @@ -109,14 +110,6 @@ impl Page { // 2. create our page, parse front matter and assign all of that let mut page = Page::default(); page.filepath = filepath.to_string(); - let path = Path::new(filepath); - page.filename = path.file_stem().expect("Couldn't get file stem").to_string_lossy().to_string(); - - // find out if we have sections - for section in path.parent().unwrap().components() { - page.sections.push(section.as_ref().to_string_lossy().to_string()); - } - page.raw_content = content.to_string(); parse_front_matter(front_matter, &mut page) .chain_err(|| format!("Error when parsing front matter of file `{}`", filepath))?; @@ -128,6 +121,26 @@ impl Page { html }; + // next find sections + // Pages with custom urls exists outside of sections + if page.url == "" { + let path = Path::new(filepath); + page.filename = path.file_stem().expect("Couldn't get file stem").to_string_lossy().to_string(); + + // find out if we have sections + for section in path.parent().unwrap().components() { + page.sections.push(section.as_ref().to_string_lossy().to_string()); + } + + // now the url + // it's either set in the front matter OR we get it from a combination of sections + slug + if page.sections.len() > 0 { + page.url = format!("/{}/{}", page.sections.join("/"), page.slug); + } else { + page.url = format!("/{}", page.slug); + }; + } + Ok(page) } @@ -205,7 +218,7 @@ Hello world"#; } #[test] - fn test_can_find_multiplie_parent_directories() { + fn test_can_find_multiple_parent_directories() { let content = r#" title = "Hello" slug = "hello-world" @@ -217,4 +230,29 @@ Hello world"#; assert_eq!(page.sections, vec!["posts".to_string(), "intro".to_string()]); } + #[test] + fn test_can_make_url_from_sections_and_slug() { + let content = r#" +title = "Hello" +slug = "hello-world" ++++ +Hello world"#; + let res = Page::from_str("posts/intro/start.md", content); + assert!(res.is_ok()); + let page = res.unwrap(); + assert_eq!(page.url, "/posts/intro/hello-world"); + } + + #[test] + fn test_can_make_url_from_sections_and_slug_root() { + let content = r#" +title = "Hello" +slug = "hello-world" ++++ +Hello world"#; + let res = Page::from_str("start.md", content); + assert!(res.is_ok()); + let page = res.unwrap(); + assert_eq!(page.url, "/hello-world"); + } }