@@ -250,6 +250,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
dependencies = [ | |||
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", | |||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", | |||
"serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", | |||
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", | |||
] | |||
@@ -8,7 +8,7 @@ tera = "0.11" | |||
serde = "1" | |||
slug = "0.1" | |||
rayon = "1" | |||
chrono = "0.4" | |||
chrono = { version = "0.4", features = ["serde"] } | |||
errors = { path = "../errors" } | |||
config = { path = "../config" } | |||
@@ -3,7 +3,6 @@ use std::collections::HashMap; | |||
use std::path::{Path, PathBuf}; | |||
use std::result::Result as StdResult; | |||
use chrono::Datelike; | |||
use tera::{Tera, Context as TeraContext}; | |||
use serde::ser::{SerializeStruct, self}; | |||
use slug::slugify; | |||
@@ -263,11 +262,10 @@ impl ser::Serialize for Page { | |||
state.serialize_field("title", &self.meta.title)?; | |||
state.serialize_field("description", &self.meta.description)?; | |||
state.serialize_field("date", &self.meta.date)?; | |||
if let Some(chrono_datetime) = self.meta.date() { | |||
let d = chrono_datetime.date(); | |||
state.serialize_field("year", &d.year())?; | |||
state.serialize_field("month", &d.month())?; | |||
state.serialize_field("day", &d.day())?; | |||
if let Some(d) = self.meta.datetime_tuple { | |||
state.serialize_field("year", &d.0)?; | |||
state.serialize_field("month", &d.1)?; | |||
state.serialize_field("day", &d.2)?; | |||
} else { | |||
state.serialize_field::<Option<usize>>("year", &None)?; | |||
state.serialize_field::<Option<usize>>("month", &None)?; | |||
@@ -11,7 +11,7 @@ use front_matter::SortBy; | |||
/// To remove if `sort_pages` is changed to work on borrowed values | |||
/// This cannot be used in `sort_pages` currently as it takes &&Page instead of &Page | |||
pub fn sort_pages_by_date(a: &&Page, b: &&Page) -> Ordering { | |||
let ord = b.meta.date().unwrap().cmp(&a.meta.date().unwrap()); | |||
let ord = b.meta.datetime.unwrap().cmp(&a.meta.datetime.unwrap()); | |||
if ord == Ordering::Equal { | |||
a.permalink.cmp(&b.permalink) | |||
} else { | |||
@@ -33,7 +33,7 @@ pub fn sort_pages(pages: Vec<Page>, sort_by: SortBy) -> (Vec<Page>, Vec<Page>) { | |||
.into_par_iter() | |||
.partition(|page| { | |||
match sort_by { | |||
SortBy::Date => page.meta.date.is_some(), | |||
SortBy::Date => page.meta.datetime.is_some(), | |||
SortBy::Weight => page.meta.weight.is_some(), | |||
_ => unreachable!() | |||
} | |||
@@ -42,7 +42,7 @@ pub fn sort_pages(pages: Vec<Page>, sort_by: SortBy) -> (Vec<Page>, Vec<Page>) { | |||
match sort_by { | |||
SortBy::Date => { | |||
can_be_sorted.par_sort_unstable_by(|a, b| { | |||
let ord = b.meta.date().unwrap().cmp(&a.meta.date().unwrap()); | |||
let ord = b.meta.datetime.unwrap().cmp(&a.meta.datetime.unwrap()); | |||
if ord == Ordering::Equal { | |||
a.permalink.cmp(&b.permalink) | |||
} else { | |||
@@ -159,6 +159,7 @@ mod tests { | |||
fn create_page_with_date(date: &str) -> Page { | |||
let mut front_matter = PageFrontMatter::default(); | |||
front_matter.date = Some(date.to_string()); | |||
front_matter.date_to_datetime(); | |||
Page::new("content/hello.md", front_matter) | |||
} | |||
@@ -62,7 +62,7 @@ fn fix_toml_dates(table: Map<String, Value>) -> Value { | |||
/// The front matter of every page | |||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] | |||
#[derive(Debug, Clone, PartialEq, Deserialize)] | |||
#[serde(default)] | |||
pub struct PageFrontMatter { | |||
/// <title> of the page | |||
@@ -72,6 +72,12 @@ pub struct PageFrontMatter { | |||
/// Date if we want to order pages (ie blog post) | |||
#[serde(default, deserialize_with = "from_toml_datetime")] | |||
pub date: Option<String>, | |||
/// Chrono converted datetime | |||
#[serde(default, skip_deserializing)] | |||
pub datetime: Option<NaiveDateTime>, | |||
/// The converted date into a (year, month, day) tuple | |||
#[serde(default, skip_deserializing)] | |||
pub datetime_tuple: Option<(i32, u32, u32)>, | |||
/// Whether this page is a draft and should be ignored for pagination etc | |||
pub draft: bool, | |||
/// The page slug. Will be used instead of the filename if present | |||
@@ -124,12 +130,16 @@ impl PageFrontMatter { | |||
Value::Object(o) => o, | |||
_ => unreachable!("Got something other than a table in page extra"), | |||
}; | |||
f.date_to_datetime(); | |||
Ok(f) | |||
} | |||
/// Converts the TOML datetime to a Chrono naive datetime | |||
pub fn date(&self) -> Option<NaiveDateTime> { | |||
if let Some(ref d) = self.date { | |||
/// Also grabs the year/month/day tuple that will be used in serialization | |||
pub fn date_to_datetime(&mut self) { | |||
self.datetime = if let Some(ref d) = self.date { | |||
if d.contains('T') { | |||
DateTime::parse_from_rfc3339(&d).ok().and_then(|s| Some(s.naive_local())) | |||
} else { | |||
@@ -137,7 +147,13 @@ impl PageFrontMatter { | |||
} | |||
} else { | |||
None | |||
} | |||
}; | |||
self.datetime_tuple = if let Some(ref dt) = self.datetime { | |||
Some((dt.year(), dt.month(), dt.day())) | |||
} else { | |||
None | |||
}; | |||
} | |||
pub fn order(&self) -> usize { | |||
@@ -155,6 +171,8 @@ impl Default for PageFrontMatter { | |||
title: None, | |||
description: None, | |||
date: None, | |||
datetime: None, | |||
datetime_tuple: None, | |||
draft: false, | |||
slug: None, | |||
path: None, | |||