@@ -18,7 +18,7 @@ dependencies = [ | |||
"slug 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", | |||
"staticfile 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | |||
"syntect 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", | |||
"tera 0.8.0 (git+https://github.com/Keats/tera)", | |||
"tera 0.8.0 (git+https://github.com/Keats/tera?branch=reload)", | |||
"toml 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", | |||
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", | |||
"ws 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", | |||
@@ -774,7 +774,7 @@ dependencies = [ | |||
[[package]] | |||
name = "tera" | |||
version = "0.8.0" | |||
source = "git+https://github.com/Keats/tera#2eb55de231e08da50ca32a443499fbce8d9003e0" | |||
source = "git+https://github.com/Keats/tera?branch=reload#31f8bd8238e3e6bdef9ecf4468079c535609b5eb" | |||
dependencies = [ | |||
"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)", | |||
@@ -1095,7 +1095,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
"checksum syn 0.11.9 (registry+https://github.com/rust-lang/crates.io-index)" = "480c834701caba3548aa991e54677281be3a5414a9d09ddbdf4ed74a569a9d19" | |||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" | |||
"checksum syntect 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f79be04af68d5fa09e71b3274159a955a25f25a5cbfba9a6ff64139b71d848a" | |||
"checksum tera 0.8.0 (git+https://github.com/Keats/tera)" = "<none>" | |||
"checksum tera 0.8.0 (git+https://github.com/Keats/tera?branch=reload)" = "<none>" | |||
"checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a" | |||
"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a" | |||
"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" | |||
@@ -20,7 +20,7 @@ glob = "0.2" | |||
serde = "0.9" | |||
serde_json = "0.9" | |||
serde_derive = "0.9" | |||
tera = { git = "https://github.com/Keats/tera", branch = "master" } | |||
tera = { git = "https://github.com/Keats/tera", branch = "reload" } | |||
# tera = "0.8" | |||
slug = "0.1" | |||
syntect = "1" | |||
@@ -87,24 +87,29 @@ pub fn serve(interface: &str, port: &str) -> Result<()> { | |||
println!("Change detected, rebuilding site"); | |||
let what_changed = detect_change_kind(&pwd, &path); | |||
let mut reload_path = String::new(); | |||
match what_changed { | |||
ChangeKind::Content => println!("Content changed {}", path.display()), | |||
ChangeKind::Templates => println!("Template changed {}", path.display()), | |||
ChangeKind::StaticFiles => println!("Static file changes detected {}", path.display()), | |||
(ChangeKind::Content, _) => println!("Content changed {}", path.display()), | |||
(ChangeKind::Templates, _) => println!("Template changed {}", path.display()), | |||
(ChangeKind::StaticFiles, p) => { | |||
reload_path = p; | |||
println!("Static file changes detected {}", path.display()); | |||
}, | |||
}; | |||
println!("Reloading {}", reload_path); | |||
let start = Instant::now(); | |||
match site.rebuild() { | |||
Ok(_) => { | |||
println!("Done in {:.1}s.", time_elapsed(start)); | |||
broadcaster.send(r#" | |||
{ | |||
println!("Done in {:.1}s.\n", time_elapsed(start)); | |||
broadcaster.send(format!(r#" | |||
{{ | |||
"command": "reload", | |||
"path": "", | |||
"path": "{}", | |||
"originalPath": "", | |||
"liveCSS": true, | |||
"liveImg": true, | |||
"protocol": ["http://livereload.com/protocols/official-7"] | |||
}"#).unwrap(); | |||
}}"#, reload_path)).unwrap(); | |||
}, | |||
Err(e) => { | |||
println!("Failed to build the site"); | |||
@@ -160,7 +165,7 @@ fn is_temp_file(path: &Path) -> bool { | |||
/// Detect what changed from the given path so we have an idea what needs | |||
/// to be reloaded | |||
fn detect_change_kind(pwd: &str, path: &Path) -> ChangeKind { | |||
fn detect_change_kind(pwd: &str, path: &Path) -> (ChangeKind, String) { | |||
let path_str = format!("{}", path.display()) | |||
.replace(pwd, "") | |||
.replace("\\", "/"); | |||
@@ -174,7 +179,7 @@ fn detect_change_kind(pwd: &str, path: &Path) -> ChangeKind { | |||
panic!("Got a change in an unexpected path: {}", path_str); | |||
}; | |||
change_kind | |||
(change_kind, path_str) | |||
} | |||
#[cfg(test)] | |||
@@ -206,9 +211,18 @@ mod tests { | |||
#[test] | |||
fn test_can_detect_kind_of_changes() { | |||
let testcases = vec![ | |||
(ChangeKind::Templates, "/home/vincent/site", Path::new("/home/vincent/site/templates/hello.html")), | |||
(ChangeKind::StaticFiles, "/home/vincent/site", Path::new("/home/vincent/site/static/site.css")), | |||
(ChangeKind::Content, "/home/vincent/site", Path::new("/home/vincent/site/content/posts/hello.md")), | |||
( | |||
(ChangeKind::Templates, "/templates/hello.html".to_string()), | |||
"/home/vincent/site", Path::new("/home/vincent/site/templates/hello.html") | |||
), | |||
( | |||
(ChangeKind::StaticFiles, "/static/site.css".to_string()), | |||
"/home/vincent/site", Path::new("/home/vincent/site/static/site.css") | |||
), | |||
( | |||
(ChangeKind::Content, "/content/posts/hello.md".to_string()), | |||
"/home/vincent/site", Path::new("/home/vincent/site/content/posts/hello.md") | |||
), | |||
]; | |||
for (expected, pwd, path) in testcases { | |||
@@ -1,11 +1,12 @@ | |||
use std::collections::HashMap; | |||
use std::iter::FromIterator; | |||
use std::fs::{create_dir, remove_dir_all}; | |||
use std::fs::{create_dir, remove_dir_all, copy, remove_file}; | |||
use std::path::Path; | |||
use glob::glob; | |||
use tera::{Tera, Context}; | |||
use slug::slugify; | |||
use walkdir::WalkDir; | |||
use errors::{Result, ResultExt}; | |||
use config::{Config, get_config}; | |||
@@ -98,7 +99,32 @@ impl Site { | |||
} | |||
/// Copy the content of the `static` folder into the `public` folder | |||
pub fn copy_static_files(&self) -> Result<()> { | |||
/// | |||
/// TODO: only copy one file if possible because that would be a waster | |||
/// to do re-copy the whole thing | |||
pub fn copy_static_directory(&self) -> Result<()> { | |||
let from = Path::new("static"); | |||
let target = Path::new("public"); | |||
for entry in WalkDir::new(from).into_iter().filter_map(|e| e.ok()) { | |||
let relative_path = entry.path().strip_prefix(&from).unwrap(); | |||
let target_path = { | |||
let mut target_path = target.to_path_buf(); | |||
target_path.push(relative_path); | |||
target_path | |||
}; | |||
if entry.path().is_dir() { | |||
if !target_path.exists() { | |||
create_dir(&target_path)?; | |||
} | |||
} else { | |||
if target_path.exists() { | |||
remove_file(&target_path)?; | |||
} | |||
copy(entry.path(), &target_path)?; | |||
} | |||
} | |||
Ok(()) | |||
} | |||
@@ -106,6 +132,7 @@ impl Site { | |||
/// Very dumb for now, ideally it would only rebuild what changed | |||
pub fn rebuild(&mut self) -> Result<()> { | |||
self.parse_site()?; | |||
self.templates.full_reload()?; | |||
self.build() | |||
} | |||
@@ -174,6 +201,7 @@ impl Site { | |||
let index = self.templates.render("index.html", &context)?; | |||
create_file(public.join("index.html"), &self.inject_livereload(index))?; | |||
self.copy_static_directory()?; | |||
Ok(()) | |||
} | |||