@@ -1,6 +1,6 @@ | |||||
[root] | [root] | ||||
name = "gutenberg" | name = "gutenberg" | ||||
version = "0.1.0" | |||||
version = "0.0.1" | |||||
dependencies = [ | dependencies = [ | ||||
"chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | "chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
"clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)", | "clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
@@ -774,7 +774,7 @@ dependencies = [ | |||||
[[package]] | [[package]] | ||||
name = "tera" | name = "tera" | ||||
version = "0.8.0" | version = "0.8.0" | ||||
source = "git+https://github.com/Keats/tera?branch=reload#31f8bd8238e3e6bdef9ecf4468079c535609b5eb" | |||||
source = "git+https://github.com/Keats/tera?branch=reload#ee038a6f3519ac35e1878ca9b29ec739a8f84a15" | |||||
dependencies = [ | dependencies = [ | ||||
"chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | "chrono 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
"error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", | "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
@@ -1,6 +1,6 @@ | |||||
[package] | [package] | ||||
name = "gutenberg" | name = "gutenberg" | ||||
version = "0.1.0" | |||||
version = "0.0.1" | |||||
authors = ["Vincent Prouillet <vincent@wearewizards.io>"] | authors = ["Vincent Prouillet <vincent@wearewizards.io>"] | ||||
license = "MIT" | license = "MIT" | ||||
readme = "README.md" | readme = "README.md" | ||||
@@ -119,11 +119,13 @@ pub fn serve(interface: &str, port: &str) -> Result<()> { | |||||
match detect_change_kind(&pwd, &path) { | match detect_change_kind(&pwd, &path) { | ||||
(ChangeKind::Content, _) => { | (ChangeKind::Content, _) => { | ||||
println!("-> Content changed {}", path.display()); | println!("-> Content changed {}", path.display()); | ||||
rebuild_done_handling(&broadcaster, site.rebuild(), ""); | |||||
// Force refresh | |||||
rebuild_done_handling(&broadcaster, site.rebuild_after_content_change(), "/x.js"); | |||||
}, | }, | ||||
(ChangeKind::Templates, _) => { | (ChangeKind::Templates, _) => { | ||||
println!("-> Template changed {}", path.display()); | println!("-> Template changed {}", path.display()); | ||||
rebuild_done_handling(&broadcaster, site.rebuild_after_template_change(), ""); | |||||
// Force refresh | |||||
rebuild_done_handling(&broadcaster, site.rebuild_after_template_change(), "/x.js"); | |||||
}, | }, | ||||
(ChangeKind::StaticFiles, p) => { | (ChangeKind::StaticFiles, p) => { | ||||
println!("-> Static file changes detected {}", path.display()); | println!("-> Static file changes detected {}", path.display()); | ||||
@@ -36,9 +36,9 @@ pub struct FrontMatter { | |||||
pub draft: Option<bool>, | pub draft: Option<bool>, | ||||
/// Only one category allowed | /// Only one category allowed | ||||
pub category: Option<String>, | pub category: Option<String>, | ||||
/// Optional layout, if we want to specify which tpl to render for that page | |||||
/// Optional template, if we want to specify which template to render for that page | |||||
#[serde(skip_serializing)] | #[serde(skip_serializing)] | ||||
pub layout: Option<String>, | |||||
pub template: Option<String>, | |||||
/// Any extra parameter present in the front matter | /// Any extra parameter present in the front matter | ||||
pub extra: Option<HashMap<String, Value>>, | pub extra: Option<HashMap<String, Value>>, | ||||
} | } | ||||
@@ -69,6 +69,7 @@ impl FrontMatter { | |||||
Ok(f) | Ok(f) | ||||
} | } | ||||
/// Converts the date in the front matter, which can be in 2 formats, into a NaiveDateTime | |||||
pub fn parse_date(&self) -> Option<NaiveDateTime> { | pub fn parse_date(&self) -> Option<NaiveDateTime> { | ||||
match self.date { | match self.date { | ||||
Some(ref d) => { | Some(ref d) => { | ||||
@@ -87,6 +87,9 @@ fn main() { | |||||
Ok(()) => (), | Ok(()) => (), | ||||
Err(e) => { | Err(e) => { | ||||
println!("Error: {}", e); | println!("Error: {}", e); | ||||
for e in e.iter().skip(1) { | |||||
println!("Reason: {}", e) | |||||
} | |||||
::std::process::exit(1); | ::std::process::exit(1); | ||||
}, | }, | ||||
}; | }; | ||||
@@ -182,22 +182,20 @@ impl Page { | |||||
Page::parse(&path.strip_prefix("content").unwrap().to_string_lossy(), &content, config) | Page::parse(&path.strip_prefix("content").unwrap().to_string_lossy(), &content, config) | ||||
} | } | ||||
fn get_layout_name(&self) -> String { | |||||
match self.meta.layout { | |||||
Some(ref l) => l.to_string(), | |||||
None => "page.html".to_string() | |||||
} | |||||
} | |||||
/// Renders the page using the default layout, unless specified in front-matter | /// Renders the page using the default layout, unless specified in front-matter | ||||
pub fn render_html(&self, tera: &Tera, config: &Config) -> Result<String> { | pub fn render_html(&self, tera: &Tera, config: &Config) -> Result<String> { | ||||
let tpl = self.get_layout_name(); | |||||
let tpl_name = match self.meta.template { | |||||
Some(ref l) => l.to_string(), | |||||
None => "page.html".to_string() | |||||
}; | |||||
// TODO: create a helper to create context to ensure all contexts | |||||
// have the same names | |||||
let mut context = Context::new(); | let mut context = Context::new(); | ||||
context.add("site", config); | |||||
context.add("config", config); | |||||
context.add("page", self); | context.add("page", self); | ||||
tera.render(&tpl, &context) | |||||
.chain_err(|| "Error while rendering template") | |||||
tera.render(&tpl_name, &context) | |||||
.chain_err(|| format!("Failed to render page '{}'", self.filename)) | |||||
} | } | ||||
} | } | ||||
@@ -225,12 +223,10 @@ impl ser::Serialize for Page { | |||||
impl PartialOrd for Page { | impl PartialOrd for Page { | ||||
fn partial_cmp(&self, other: &Page) -> Option<Ordering> { | fn partial_cmp(&self, other: &Page) -> Option<Ordering> { | ||||
if self.meta.date.is_none() { | if self.meta.date.is_none() { | ||||
println!("No self data"); | |||||
return Some(Ordering::Less); | return Some(Ordering::Less); | ||||
} | } | ||||
if other.meta.date.is_none() { | if other.meta.date.is_none() { | ||||
println!("No other date"); | |||||
return Some(Ordering::Greater); | return Some(Ordering::Greater); | ||||
} | } | ||||
@@ -337,7 +333,6 @@ Hello world"#; | |||||
assert!(res.is_ok()); | assert!(res.is_ok()); | ||||
let page = res.unwrap(); | let page = res.unwrap(); | ||||
assert_eq!(page.url, "posts/intro/hello-world"); | assert_eq!(page.url, "posts/intro/hello-world"); | ||||
println!("{}", page.permalink); | |||||
assert_eq!(page.permalink, format!("{}{}", conf.base_url, "/posts/intro/hello-world")); | assert_eq!(page.permalink, format!("{}{}", conf.base_url, "/posts/intro/hello-world")); | ||||
} | } | ||||
@@ -149,16 +149,13 @@ impl Site { | |||||
Ok(()) | Ok(()) | ||||
} | } | ||||
/// Re-parse and re-generate the site | |||||
/// Very dumb for now, ideally it would only rebuild what changed | |||||
pub fn rebuild(&mut self) -> Result<()> { | |||||
pub fn rebuild_after_content_change(&mut self) -> Result<()> { | |||||
self.parse_site()?; | self.parse_site()?; | ||||
self.build() | self.build() | ||||
} | } | ||||
pub fn rebuild_after_template_change(&mut self) -> Result<()> { | pub fn rebuild_after_template_change(&mut self) -> Result<()> { | ||||
self.templates.full_reload()?; | self.templates.full_reload()?; | ||||
println!("Reloaded templates"); | |||||
self.build_pages() | self.build_pages() | ||||
} | } | ||||