Copy static directory and live reload changes to it
This commit is contained in:
parent
478e7054de
commit
57fd159025
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -18,7 +18,7 @@ dependencies = [
|
||||||
"slug 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"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)",
|
"ws 0.6.0 (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#2eb55de231e08da50ca32a443499fbce8d9003e0"
|
source = "git+https://github.com/Keats/tera?branch=reload#31f8bd8238e3e6bdef9ecf4468079c535609b5eb"
|
||||||
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)",
|
||||||
|
@ -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 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 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 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 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-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"
|
"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 = "0.9"
|
||||||
serde_json = "0.9"
|
serde_json = "0.9"
|
||||||
serde_derive = "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"
|
# tera = "0.8"
|
||||||
slug = "0.1"
|
slug = "0.1"
|
||||||
syntect = "1"
|
syntect = "1"
|
||||||
|
|
|
@ -87,24 +87,29 @@ pub fn serve(interface: &str, port: &str) -> Result<()> {
|
||||||
|
|
||||||
println!("Change detected, rebuilding site");
|
println!("Change detected, rebuilding site");
|
||||||
let what_changed = detect_change_kind(&pwd, &path);
|
let what_changed = detect_change_kind(&pwd, &path);
|
||||||
|
let mut reload_path = String::new();
|
||||||
match what_changed {
|
match what_changed {
|
||||||
ChangeKind::Content => println!("Content changed {}", path.display()),
|
(ChangeKind::Content, _) => println!("Content changed {}", path.display()),
|
||||||
ChangeKind::Templates => println!("Template changed {}", path.display()),
|
(ChangeKind::Templates, _) => println!("Template changed {}", path.display()),
|
||||||
ChangeKind::StaticFiles => println!("Static file changes detected {}", path.display()),
|
(ChangeKind::StaticFiles, p) => {
|
||||||
|
reload_path = p;
|
||||||
|
println!("Static file changes detected {}", path.display());
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
println!("Reloading {}", reload_path);
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
match site.rebuild() {
|
match site.rebuild() {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
println!("Done in {:.1}s.", time_elapsed(start));
|
println!("Done in {:.1}s.\n", time_elapsed(start));
|
||||||
broadcaster.send(r#"
|
broadcaster.send(format!(r#"
|
||||||
{
|
{{
|
||||||
"command": "reload",
|
"command": "reload",
|
||||||
"path": "",
|
"path": "{}",
|
||||||
"originalPath": "",
|
"originalPath": "",
|
||||||
"liveCSS": true,
|
"liveCSS": true,
|
||||||
"liveImg": true,
|
"liveImg": true,
|
||||||
"protocol": ["http://livereload.com/protocols/official-7"]
|
"protocol": ["http://livereload.com/protocols/official-7"]
|
||||||
}"#).unwrap();
|
}}"#, reload_path)).unwrap();
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Failed to build the site");
|
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
|
/// Detect what changed from the given path so we have an idea what needs
|
||||||
/// to be reloaded
|
/// 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())
|
let path_str = format!("{}", path.display())
|
||||||
.replace(pwd, "")
|
.replace(pwd, "")
|
||||||
.replace("\\", "/");
|
.replace("\\", "/");
|
||||||
|
@ -174,7 +179,7 @@ fn detect_change_kind(pwd: &str, path: &Path) -> ChangeKind {
|
||||||
panic!("Got a change in an unexpected path: {}", path_str);
|
panic!("Got a change in an unexpected path: {}", path_str);
|
||||||
};
|
};
|
||||||
|
|
||||||
change_kind
|
(change_kind, path_str)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -206,9 +211,18 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_can_detect_kind_of_changes() {
|
fn test_can_detect_kind_of_changes() {
|
||||||
let testcases = vec![
|
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::Templates, "/templates/hello.html".to_string()),
|
||||||
(ChangeKind::Content, "/home/vincent/site", Path::new("/home/vincent/site/content/posts/hello.md")),
|
"/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 {
|
for (expected, pwd, path) in testcases {
|
||||||
|
|
32
src/site.rs
32
src/site.rs
|
@ -1,11 +1,12 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::iter::FromIterator;
|
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 std::path::Path;
|
||||||
|
|
||||||
use glob::glob;
|
use glob::glob;
|
||||||
use tera::{Tera, Context};
|
use tera::{Tera, Context};
|
||||||
use slug::slugify;
|
use slug::slugify;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
use errors::{Result, ResultExt};
|
use errors::{Result, ResultExt};
|
||||||
use config::{Config, get_config};
|
use config::{Config, get_config};
|
||||||
|
@ -98,7 +99,32 @@ impl Site {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy the content of the `static` folder into the `public` folder
|
/// 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +132,7 @@ impl Site {
|
||||||
/// Very dumb for now, ideally it would only rebuild what changed
|
/// Very dumb for now, ideally it would only rebuild what changed
|
||||||
pub fn rebuild(&mut self) -> Result<()> {
|
pub fn rebuild(&mut self) -> Result<()> {
|
||||||
self.parse_site()?;
|
self.parse_site()?;
|
||||||
|
self.templates.full_reload()?;
|
||||||
self.build()
|
self.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,6 +201,7 @@ impl Site {
|
||||||
let index = self.templates.render("index.html", &context)?;
|
let index = self.templates.render("index.html", &context)?;
|
||||||
create_file(public.join("index.html"), &self.inject_livereload(index))?;
|
create_file(public.join("index.html"), &self.inject_livereload(index))?;
|
||||||
|
|
||||||
|
self.copy_static_directory()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue