Set date from filename

Fix #396
This commit is contained in:
Vincent Prouillet 2018-10-25 16:22:00 +02:00
parent 0f6c0736cb
commit db4def63dc
6 changed files with 70 additions and 2 deletions

View file

@ -36,6 +36,7 @@ sections up to the index to be used with the `get_section` Tera function
- `serve` will now try to find other ports than 1111 rather than panicking - `serve` will now try to find other ports than 1111 rather than panicking
- Ensure content directory exists before rendering aliases - Ensure content directory exists before rendering aliases
- Do not include drafts in pagination - Do not include drafts in pagination
- Pages filenames starting by a date will now use that date as page date if there isn't one defined in frontmatter
## 0.4.2 (2018-09-03) ## 0.4.2 (2018-09-03)

2
Cargo.lock generated
View file

@ -1080,7 +1080,9 @@ dependencies = [
"errors 0.1.0", "errors 0.1.0",
"front_matter 0.1.0", "front_matter 0.1.0",
"globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rendering 0.1.0", "rendering 0.1.0",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -11,6 +11,8 @@ tera = "0.11"
serde = "1" serde = "1"
serde_derive = "1" serde_derive = "1"
slug = "0.1" slug = "0.1"
regex = "1"
lazy_static = "1"
front_matter = { path = "../front_matter" } front_matter = { path = "../front_matter" }
config = { path = "../config" } config = { path = "../config" }

View file

@ -5,6 +5,7 @@ use std::path::{Path, PathBuf};
use tera::{Tera, Context as TeraContext}; use tera::{Tera, Context as TeraContext};
use slug::slugify; use slug::slugify;
use slotmap::{Key}; use slotmap::{Key};
use regex::Regex;
use errors::{Result, ResultExt}; use errors::{Result, ResultExt};
use config::Config; use config::Config;
@ -18,6 +19,11 @@ use library::Library;
use content::file_info::FileInfo; use content::file_info::FileInfo;
use content::ser::SerializingPage; use content::ser::SerializingPage;
lazy_static! {
// Check whether a string starts with yyyy-mm-dd{-,_}
static ref DATE_IN_FILENAME: Regex = Regex::new(r"^^([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))(_|-)").unwrap();
}
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct Page { pub struct Page {
@ -103,10 +109,20 @@ impl Page {
pub fn parse(file_path: &Path, content: &str, config: &Config) -> Result<Page> { pub fn parse(file_path: &Path, content: &str, config: &Config) -> Result<Page> {
let (meta, content) = split_page_content(file_path, content)?; let (meta, content) = split_page_content(file_path, content)?;
let mut page = Page::new(file_path, meta); let mut page = Page::new(file_path, meta);
page.raw_content = content; page.raw_content = content;
let (word_count, reading_time) = get_reading_analytics(&page.raw_content); let (word_count, reading_time) = get_reading_analytics(&page.raw_content);
page.word_count = Some(word_count); page.word_count = Some(word_count);
page.reading_time = Some(reading_time); page.reading_time = Some(reading_time);
let mut has_date_in_name = false;
if DATE_IN_FILENAME.is_match(&page.file.name) {
has_date_in_name = true;
if page.meta.date.is_none() {
page.meta.date = Some(page.file.name[..10].to_string());
}
}
page.slug = { page.slug = {
if let Some(ref slug) = page.meta.slug { if let Some(ref slug) = page.meta.slug {
slug.trim().to_string() slug.trim().to_string()
@ -114,10 +130,15 @@ impl Page {
if let Some(parent) = page.file.path.parent() { if let Some(parent) = page.file.path.parent() {
slugify(parent.file_name().unwrap().to_str().unwrap()) slugify(parent.file_name().unwrap().to_str().unwrap())
} else { } else {
slugify(page.file.name.clone()) slugify(&page.file.name)
} }
} else { } else {
slugify(page.file.name.clone()) if has_date_in_name {
// skip the date + the {_,-}
slugify(&page.file.name[11..])
} else {
slugify(&page.file.name)
}
} }
}; };
@ -499,4 +520,38 @@ Hello world
assert_eq!(page.assets.len(), 1); assert_eq!(page.assets.len(), 1);
assert_eq!(page.assets[0].file_name().unwrap().to_str(), Some("graph.jpg")); assert_eq!(page.assets[0].file_name().unwrap().to_str(), Some("graph.jpg"));
} }
#[test]
fn can_get_date_from_filename() {
let config = Config::default();
let content = r#"
+++
+++
Hello world
<!-- more -->"#.to_string();
let res = Page::parse(Path::new("2018-10-08_hello.md"), &content, &config);
assert!(res.is_ok());
let page = res.unwrap();
assert_eq!(page.meta.date, Some("2018-10-08".to_string()));
assert_eq!(page.slug, "hello");
}
#[test]
fn frontmatter_date_override_filename_date() {
let config = Config::default();
let content = r#"
+++
date = 2018-09-09
+++
Hello world
<!-- more -->"#.to_string();
let res = Page::parse(Path::new("2018-10-08_hello.md"), &content, &config);
assert!(res.is_ok());
let page = res.unwrap();
assert_eq!(page.meta.date, Some("2018-09-09".to_string()));
assert_eq!(page.slug, "hello");
}
} }

View file

@ -6,6 +6,9 @@ extern crate serde_derive;
extern crate chrono; extern crate chrono;
extern crate slotmap; extern crate slotmap;
extern crate rayon; extern crate rayon;
#[macro_use]
extern crate lazy_static;
extern crate regex;
#[cfg(test)] #[cfg(test)]
extern crate tempfile; extern crate tempfile;

View file

@ -16,6 +16,10 @@ create a **page** at `[base_url]/about`).
If the file is given any name *other* than `index.md` or `_index.md`, then it will If the file is given any name *other* than `index.md` or `_index.md`, then it will
create a page with that name (without the `.md`). So naming a file in the root of your create a page with that name (without the `.md`). So naming a file in the root of your
content directory `about.md` would also create a page at `[base_url]/about`. content directory `about.md` would also create a page at `[base_url]/about`.
Another exception to that rule is that a filename starting with a YYYY-mm-dd date followed by
an underscore (`_`) or a dash (`-`) will use that date as the page date, unless already set
in the front-matter. The page name will be anything after `_`/`-` so a filename like `2018-10-10-hello-world.md` will
be available at `[base_url]/hello-world`
As you can see, creating an `about.md` file is exactly equivalent to creating an As you can see, creating an `about.md` file is exactly equivalent to creating an
`about/index.md` file. The only difference between the two methods is that creating `about/index.md` file. The only difference between the two methods is that creating
@ -42,6 +46,7 @@ description = ""
# Do not wrap dates in quotes, the line below only indicates that there is no default date. # Do not wrap dates in quotes, the line below only indicates that there is no default date.
# If the section variable `sort_by` is set to `date`, then any page that lacks a `date` # If the section variable `sort_by` is set to `date`, then any page that lacks a `date`
# will not be rendered. # will not be rendered.
# Setting this overrides a date set in the filename.
date = date =
# The weight as defined in the Section page # The weight as defined in the Section page