parent
43b68f790d
commit
afc30543cc
|
@ -42,6 +42,7 @@ sections up to the index to be used with the `get_section` Tera function
|
||||||
- Add `transparent` sections, for when you want to separate content by sections but want to group them at a higher level (think a `posts` folder with years
|
- Add `transparent` sections, for when you want to separate content by sections but want to group them at a higher level (think a `posts` folder with years
|
||||||
that want to use pagination on the index).
|
that want to use pagination on the index).
|
||||||
- Add `page_template` to section front-matter for when you want to specify the template to use for every page under it
|
- Add `page_template` to section front-matter for when you want to specify the template to use for every page under it
|
||||||
|
- Improves to `zola serve`: now handles files/directories renaming
|
||||||
|
|
||||||
## 0.4.2 (2018-09-03)
|
## 0.4.2 (2018-09-03)
|
||||||
|
|
||||||
|
|
24
Cargo.lock
generated
24
Cargo.lock
generated
|
@ -86,7 +86,7 @@ dependencies = [
|
||||||
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_urlencoded 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_urlencoded 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -506,7 +506,7 @@ dependencies = [
|
||||||
"rust-stemmers 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rust-stemmers 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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)",
|
||||||
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"strum 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"strum 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"strum_macros 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"strum_macros 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -1140,7 +1140,7 @@ dependencies = [
|
||||||
"phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
"phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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)",
|
||||||
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1385,7 +1385,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "onig"
|
name = "onig"
|
||||||
version = "4.2.0"
|
version = "4.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1751,7 +1751,7 @@ dependencies = [
|
||||||
"mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_urlencoded 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_urlencoded 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1907,7 +1907,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.32"
|
version = "1.0.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2119,12 +2119,12 @@ dependencies = [
|
||||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"onig 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"onig 4.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"plist 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"plist 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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)",
|
||||||
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"walkdir 2.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"walkdir 2.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"yaml-rust 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"yaml-rust 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -2156,7 +2156,7 @@ dependencies = [
|
||||||
"library 0.1.0",
|
"library 0.1.0",
|
||||||
"pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"reqwest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"reqwest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tera 0.11.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tera 0.11.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"toml 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2187,7 +2187,7 @@ dependencies = [
|
||||||
"pest_derive 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pest_derive 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unic-segment 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unic-segment 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2946,7 +2946,7 @@ dependencies = [
|
||||||
"checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10"
|
"checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10"
|
||||||
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
||||||
"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
|
"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
|
||||||
"checksum onig 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f0d9dac9b8a5211103d75f3ce8d0c799e6f4f3f22608eeaefb4419786e4b258"
|
"checksum onig 4.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3febe8cb22362af9e662c9c35e4d8a675de50b1b119823aa556892ac967fb776"
|
||||||
"checksum onig_sys 69.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "78c04019a39ebac42dfd8c7822af0a009043720845a812ddbb95e403298b0183"
|
"checksum onig_sys 69.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "78c04019a39ebac42dfd8c7822af0a009043720845a812ddbb95e403298b0183"
|
||||||
"checksum openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "5e1309181cdcbdb51bc3b6bedb33dfac2a83b3d585033d3f6d9e22e8c1928613"
|
"checksum openssl 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "5e1309181cdcbdb51bc3b6bedb33dfac2a83b3d585033d3f6d9e22e8c1928613"
|
||||||
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
|
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
|
||||||
|
@ -3001,7 +3001,7 @@ dependencies = [
|
||||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||||
"checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef"
|
"checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef"
|
||||||
"checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c"
|
"checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c"
|
||||||
"checksum serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "43344e7ce05d0d8280c5940cabb4964bea626aa58b1ec0e8c73fa2a8512a38ce"
|
"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811"
|
||||||
"checksum serde_urlencoded 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aaed41d9fb1e2f587201b863356590c90c1157495d811430a0c0325fe8169650"
|
"checksum serde_urlencoded 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "aaed41d9fb1e2f587201b863356590c90c1157495d811430a0c0325fe8169650"
|
||||||
"checksum sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded"
|
"checksum sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded"
|
||||||
"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
|
"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
|
||||||
|
|
|
@ -277,8 +277,8 @@ impl Library {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_parent_section(&self, path: &Path) -> Option<&Section> {
|
pub fn find_parent_section<P: AsRef<Path>>(&self, path: P) -> Option<&Section> {
|
||||||
let page_key = self.paths_to_pages[path];
|
let page_key = self.paths_to_pages[path.as_ref()];
|
||||||
for s in self.sections.values() {
|
for s in self.sections.values() {
|
||||||
if s.pages.contains(&page_key) {
|
if s.pages.contains(&page_key) {
|
||||||
return Some(s);
|
return Some(s);
|
||||||
|
@ -289,16 +289,16 @@ impl Library {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Only used in tests
|
/// Only used in tests
|
||||||
pub fn get_section_key(&self, path: &PathBuf) -> Option<&Key> {
|
pub fn get_section_key<P: AsRef<Path>>(&self, path: P) -> Option<&Key> {
|
||||||
self.paths_to_sections.get(path)
|
self.paths_to_sections.get(path.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_section(&self, path: &PathBuf) -> Option<&Section> {
|
pub fn get_section<P: AsRef<Path>>(&self, path: P) -> Option<&Section> {
|
||||||
self.sections.get(self.paths_to_sections.get(path).cloned().unwrap_or_default())
|
self.sections.get(self.paths_to_sections.get(path.as_ref()).cloned().unwrap_or_default())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_section_mut(&mut self, path: &PathBuf) -> Option<&mut Section> {
|
pub fn get_section_mut<P: AsRef<Path>>(&mut self, path: P) -> Option<&mut Section> {
|
||||||
self.sections.get_mut(self.paths_to_sections.get(path).cloned().unwrap_or_default())
|
self.sections.get_mut(self.paths_to_sections.get(path.as_ref()).cloned().unwrap_or_default())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_section_by_key(&self, key: Key) -> &Section {
|
pub fn get_section_by_key(&self, key: Key) -> &Section {
|
||||||
|
@ -313,8 +313,8 @@ impl Library {
|
||||||
&self.get_section_by_key(key).file.relative
|
&self.get_section_by_key(key).file.relative
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_page(&self, path: &PathBuf) -> Option<&Page> {
|
pub fn get_page<P: AsRef<Path>>(&self, path: P) -> Option<&Page> {
|
||||||
self.pages.get(self.paths_to_pages.get(path).cloned().unwrap_or_default())
|
self.pages.get(self.paths_to_pages.get(path.as_ref()).cloned().unwrap_or_default())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_page_by_key(&self, key: Key) -> &Page {
|
pub fn get_page_by_key(&self, key: Key) -> &Page {
|
||||||
|
@ -325,16 +325,16 @@ impl Library {
|
||||||
self.pages.get_mut(key).unwrap()
|
self.pages.get_mut(key).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_section(&mut self, path: &PathBuf) -> Option<Section> {
|
pub fn remove_section<P: AsRef<Path>>(&mut self, path: P) -> Option<Section> {
|
||||||
if let Some(k) = self.paths_to_sections.remove(path) {
|
if let Some(k) = self.paths_to_sections.remove(path.as_ref()) {
|
||||||
self.sections.remove(k)
|
self.sections.remove(k)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_page(&mut self, path: &PathBuf) -> Option<Page> {
|
pub fn remove_page<P: AsRef<Path>>(&mut self, path: P) -> Option<Page> {
|
||||||
if let Some(k) = self.paths_to_pages.remove(path) {
|
if let Some(k) = self.paths_to_pages.remove(path.as_ref()) {
|
||||||
self.pages.remove(k)
|
self.pages.remove(k)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -342,12 +342,12 @@ impl Library {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used in rebuild, to check if we know it already
|
/// Used in rebuild, to check if we know it already
|
||||||
pub fn contains_section(&self, path: &PathBuf) -> bool {
|
pub fn contains_section<P: AsRef<Path>>(&self, path: P) -> bool {
|
||||||
self.paths_to_sections.contains_key(path)
|
self.paths_to_sections.contains_key(path.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used in rebuild, to check if we know it already
|
/// Used in rebuild, to check if we know it already
|
||||||
pub fn contains_page(&self, path: &PathBuf) -> bool {
|
pub fn contains_page<P: AsRef<Path>>(&self, path: P) -> bool {
|
||||||
self.paths_to_pages.contains_key(path)
|
self.paths_to_pages.contains_key(path.as_ref())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,7 +240,53 @@ fn handle_page_editing(site: &mut Site, path: &Path) -> Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// What happens when a section or a page is changed
|
|
||||||
|
/// What happens when we rename a file/folder in the content directory.
|
||||||
|
/// Note that this is only called for folders when it isn't empty
|
||||||
|
pub fn after_content_rename(site: &mut Site, old: &Path, new: &Path) -> Result<()> {
|
||||||
|
let new_path = if new.is_dir() {
|
||||||
|
if new.join("_index.md").exists() {
|
||||||
|
// This is a section keep the dir folder to differentiate from renaming _index.md
|
||||||
|
// which doesn't do the same thing
|
||||||
|
new.to_path_buf()
|
||||||
|
} else if new.join("index.md").exists() {
|
||||||
|
new.join("index.md")
|
||||||
|
} else {
|
||||||
|
bail!("Got unexpected folder {:?} while handling renaming that was not expected", new);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
new.to_path_buf()
|
||||||
|
};
|
||||||
|
|
||||||
|
// A section folder has been renamed: just reload the whole site and rebuild it as we
|
||||||
|
// do not really know what needs to be rendered
|
||||||
|
if new_path.is_dir() {
|
||||||
|
site.load()?;
|
||||||
|
return site.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renaming a file to _index.md, let the section editing do something and hope for the best
|
||||||
|
if new_path.file_name().unwrap() == "_index.md" {
|
||||||
|
// We aren't entirely sure where the original thing was so just try to delete whatever was
|
||||||
|
// at the old path
|
||||||
|
site.library.remove_page(&old.to_path_buf());
|
||||||
|
site.library.remove_section(&old.to_path_buf());
|
||||||
|
return handle_section_editing(site, &new_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it is a page, just delete what was there before and
|
||||||
|
// fake it's a new page
|
||||||
|
let old_path = if new_path.file_name().unwrap() == "index.md" {
|
||||||
|
old.join("index.md")
|
||||||
|
} else {
|
||||||
|
old.to_path_buf()
|
||||||
|
};
|
||||||
|
site.library.remove_page(&old_path);
|
||||||
|
return handle_page_editing(site, &new_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// What happens when a section or a page is created/edited
|
||||||
pub fn after_content_change(site: &mut Site, path: &Path) -> Result<()> {
|
pub fn after_content_change(site: &mut Site, path: &Path) -> Result<()> {
|
||||||
let is_section = path.file_name().unwrap() == "_index.md";
|
let is_section = path.file_name().unwrap() == "_index.md";
|
||||||
let is_md = path.extension().unwrap() == "md";
|
let is_md = path.extension().unwrap() == "md";
|
||||||
|
|
|
@ -4,14 +4,14 @@ extern crate site;
|
||||||
extern crate tempfile;
|
extern crate tempfile;
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::{remove_dir_all, File};
|
use std::fs::{self, File};
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
|
||||||
use fs_extra::dir;
|
use fs_extra::dir;
|
||||||
use site::Site;
|
use site::Site;
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
use rebuild::after_content_change;
|
use rebuild::{after_content_change, after_content_rename};
|
||||||
|
|
||||||
// Loads the test_site in a tempdir and build it there
|
// Loads the test_site in a tempdir and build it there
|
||||||
// Returns (site_path_in_tempdir, site)
|
// Returns (site_path_in_tempdir, site)
|
||||||
|
@ -25,10 +25,6 @@ macro_rules! load_and_build_site {
|
||||||
dir::copy(&path, &$tmp_dir, &options).unwrap();
|
dir::copy(&path, &$tmp_dir, &options).unwrap();
|
||||||
|
|
||||||
let site_path = $tmp_dir.path().join("test_site");
|
let site_path = $tmp_dir.path().join("test_site");
|
||||||
// delete useless sections for those tests
|
|
||||||
remove_dir_all(site_path.join("content").join("paginated")).unwrap();
|
|
||||||
remove_dir_all(site_path.join("content").join("posts")).unwrap();
|
|
||||||
|
|
||||||
let mut site = Site::new(&site_path, "config.toml").unwrap();
|
let mut site = Site::new(&site_path, "config.toml").unwrap();
|
||||||
site.load().unwrap();
|
site.load().unwrap();
|
||||||
let public = &site_path.join("public");
|
let public = &site_path.join("public");
|
||||||
|
@ -67,6 +63,22 @@ macro_rules! file_contains {
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Rename a file or a folder to the new given name
|
||||||
|
macro_rules! rename {
|
||||||
|
($site_path: expr, $path: expr, $new_name: expr) => {{
|
||||||
|
let mut t = $site_path.clone();
|
||||||
|
for c in $path.split('/') {
|
||||||
|
t.push(c);
|
||||||
|
}
|
||||||
|
let mut new_path = t.parent().unwrap().to_path_buf();
|
||||||
|
new_path.push($new_name);
|
||||||
|
fs::rename(&t, &new_path).unwrap();
|
||||||
|
println!("Renamed {:?} to {:?}", t, new_path);
|
||||||
|
(t, new_path)
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_rebuild_after_simple_change_to_page_content() {
|
fn can_rebuild_after_simple_change_to_page_content() {
|
||||||
let tmp_dir = tempdir().expect("create temp dir");
|
let tmp_dir = tempdir().expect("create temp dir");
|
||||||
|
@ -135,3 +147,87 @@ template = "rebuild.html"
|
||||||
"<h1>first</h1><h1>second</h1>"
|
"<h1>first</h1><h1>second</h1>"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_rebuild_after_transparent_change() {
|
||||||
|
let tmp_dir = tempdir().expect("create temp dir");
|
||||||
|
let (site_path, mut site) = load_and_build_site!(tmp_dir);
|
||||||
|
let file_path = edit_file!(
|
||||||
|
site_path,
|
||||||
|
"content/posts/2018/_index.md",
|
||||||
|
br#"
|
||||||
|
+++
|
||||||
|
transparent = false
|
||||||
|
render = false
|
||||||
|
+++
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
// Also remove pagination from posts section so we check whether the transparent page title
|
||||||
|
// is there or not without dealing with pagination
|
||||||
|
edit_file!(
|
||||||
|
site_path,
|
||||||
|
"content/posts/_index.md",
|
||||||
|
br#"
|
||||||
|
+++
|
||||||
|
template = "section.html"
|
||||||
|
insert_anchor_links = "left"
|
||||||
|
+++
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
|
||||||
|
let res = after_content_change(&mut site, &file_path);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
assert!(!file_contains!(
|
||||||
|
site_path,
|
||||||
|
"public/posts/index.html",
|
||||||
|
"A transparent page"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_rebuild_after_renaming_page() {
|
||||||
|
let tmp_dir = tempdir().expect("create temp dir");
|
||||||
|
let (site_path, mut site) = load_and_build_site!(tmp_dir);
|
||||||
|
let (old_path, new_path) = rename!(site_path, "content/posts/simple.md", "hard.md");
|
||||||
|
|
||||||
|
let res = after_content_rename(&mut site, &old_path, &new_path);
|
||||||
|
println!("{:?}", res);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
assert!(file_contains!(
|
||||||
|
site_path,
|
||||||
|
"public/posts/hard/index.html",
|
||||||
|
"A simple page"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/Keats/gutenberg/issues/385
|
||||||
|
#[test]
|
||||||
|
fn can_rebuild_after_renaming_colocated_asset_folder() {
|
||||||
|
let tmp_dir = tempdir().expect("create temp dir");
|
||||||
|
let (site_path, mut site) = load_and_build_site!(tmp_dir);
|
||||||
|
let (old_path, new_path) = rename!(site_path, "content/posts/with-assets", "with-assets-updated");
|
||||||
|
assert!(file_contains!(site_path, "content/posts/with-assets-updated/index.md", "Hello"));
|
||||||
|
|
||||||
|
let res = after_content_rename(&mut site, &old_path, &new_path);
|
||||||
|
println!("{:?}", res);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
assert!(file_contains!(
|
||||||
|
site_path,
|
||||||
|
"public/posts/with-assets-updated/index.html",
|
||||||
|
"Hello world"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/Keats/gutenberg/issues/385
|
||||||
|
#[test]
|
||||||
|
fn can_rebuild_after_renaming_section_folder() {
|
||||||
|
let tmp_dir = tempdir().expect("create temp dir");
|
||||||
|
let (site_path, mut site) = load_and_build_site!(tmp_dir);
|
||||||
|
let (old_path, new_path) = rename!(site_path, "content/posts", "new-posts");
|
||||||
|
assert!(file_contains!(site_path, "content/new-posts/simple.md", "simple"));
|
||||||
|
|
||||||
|
let res = after_content_rename(&mut site, &old_path, &new_path);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
|
||||||
|
assert!(file_contains!(site_path, "public/new-posts/simple/index.html", "simple"));
|
||||||
|
}
|
||||||
|
|
169
src/cmd/serve.rs
169
src/cmd/serve.rs
|
@ -22,7 +22,7 @@
|
||||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::{remove_dir_all, File};
|
use std::fs::{remove_dir_all, File, read_dir};
|
||||||
use std::io::{self, Read};
|
use std::io::{self, Read};
|
||||||
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
|
use std::path::{Path, PathBuf, MAIN_SEPARATOR};
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
|
@ -225,7 +225,7 @@ pub fn serve(
|
||||||
.bind(&address)
|
.bind(&address)
|
||||||
.expect("Can't start the webserver")
|
.expect("Can't start the webserver")
|
||||||
.shutdown_timeout(20);
|
.shutdown_timeout(20);
|
||||||
println!("Web server is available at http://{}", &address);
|
println!("Web server is available at http://{}\n", &address);
|
||||||
s.run();
|
s.run();
|
||||||
});
|
});
|
||||||
// The websocket for livereload
|
// The websocket for livereload
|
||||||
|
@ -286,11 +286,122 @@ pub fn serve(
|
||||||
|
|
||||||
use notify::DebouncedEvent::*;
|
use notify::DebouncedEvent::*;
|
||||||
|
|
||||||
|
let reload_templates = |site: &mut Site, path: &Path| {
|
||||||
|
let msg = if path.is_dir() {
|
||||||
|
format!("-> Directory in `templates` folder changed {}", path.display())
|
||||||
|
} else {
|
||||||
|
format!("-> Template changed {}", path.display())
|
||||||
|
};
|
||||||
|
console::info(&msg);
|
||||||
|
if let Some(ref broadcaster) = broadcaster {
|
||||||
|
// Force refresh
|
||||||
|
rebuild_done_handling(
|
||||||
|
broadcaster,
|
||||||
|
rebuild::after_template_change(site, &path),
|
||||||
|
"/x.js",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let reload_sass = |site: &Site, path: &Path, partial_path: &Path| {
|
||||||
|
let msg = if path.is_dir() {
|
||||||
|
format!("-> Directory in `sass` folder changed {}", path.display())
|
||||||
|
} else {
|
||||||
|
format!("-> Sass file changed {}", path.display())
|
||||||
|
};
|
||||||
|
console::info(&msg);
|
||||||
|
if let Some(ref broadcaster) = broadcaster {
|
||||||
|
rebuild_done_handling(
|
||||||
|
&broadcaster,
|
||||||
|
site.compile_sass(&site.base_path),
|
||||||
|
&partial_path.to_string_lossy(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let copy_static = |site: &Site, path: &Path, partial_path: &Path| {
|
||||||
|
// Do nothing if the file/dir was deleted
|
||||||
|
if !path.exists() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let msg = if path.is_dir() {
|
||||||
|
format!("-> Directory in `static` folder changed {}", path.display())
|
||||||
|
} else {
|
||||||
|
format!("-> Static file changed {}", path.display())
|
||||||
|
};
|
||||||
|
|
||||||
|
console::info(&msg);
|
||||||
|
if let Some(ref broadcaster) = broadcaster {
|
||||||
|
if path.is_dir() {
|
||||||
|
rebuild_done_handling(
|
||||||
|
broadcaster,
|
||||||
|
site.copy_static_directories(),
|
||||||
|
&path.to_string_lossy(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
rebuild_done_handling(
|
||||||
|
broadcaster,
|
||||||
|
copy_file(&path, &site.output_path, &site.static_path),
|
||||||
|
&partial_path.to_string_lossy(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match rx.recv() {
|
match rx.recv() {
|
||||||
Ok(event) => {
|
Ok(event) => {
|
||||||
match event {
|
match event {
|
||||||
Create(path) | Write(path) | Remove(path) | Rename(_, path) => {
|
Rename(old_path, path) => {
|
||||||
|
if path.is_file() && is_temp_file(&path) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let (change_kind, partial_path) = detect_change_kind(&pwd, &path);
|
||||||
|
|
||||||
|
// We only care about changes in non-empty folders
|
||||||
|
if path.is_dir() && is_folder_empty(&path) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Change detected @ {}",
|
||||||
|
Local::now().format("%Y-%m-%d %H:%M:%S").to_string()
|
||||||
|
);
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
match change_kind {
|
||||||
|
ChangeKind::Content => {
|
||||||
|
console::info(&format!("-> Content renamed {}", path.display()));
|
||||||
|
if let Some(ref broadcaster) = broadcaster {
|
||||||
|
// Force refresh
|
||||||
|
rebuild_done_handling(
|
||||||
|
broadcaster,
|
||||||
|
rebuild::after_content_rename(&mut site, &old_path, &path),
|
||||||
|
"/x.js",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ChangeKind::Templates => reload_templates(&mut site, &path),
|
||||||
|
ChangeKind::StaticFiles => copy_static(&site, &path, &partial_path),
|
||||||
|
ChangeKind::Sass => reload_sass(&site, &path, &partial_path),
|
||||||
|
ChangeKind::Config => {
|
||||||
|
console::info("-> Config changed. The whole site will be reloaded. The browser needs to be refreshed to make the changes visible.");
|
||||||
|
site = create_new_site(
|
||||||
|
interface,
|
||||||
|
port,
|
||||||
|
output_dir,
|
||||||
|
base_url,
|
||||||
|
config_file,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console::report_elapsed_time(start);
|
||||||
|
|
||||||
|
}
|
||||||
|
Create(path) | Write(path) | Remove(path) => {
|
||||||
if is_temp_file(&path) || path.is_dir() {
|
if is_temp_file(&path) || path.is_dir() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -299,6 +410,7 @@ pub fn serve(
|
||||||
"Change detected @ {}",
|
"Change detected @ {}",
|
||||||
Local::now().format("%Y-%m-%d %H:%M:%S").to_string()
|
Local::now().format("%Y-%m-%d %H:%M:%S").to_string()
|
||||||
);
|
);
|
||||||
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
match detect_change_kind(&pwd, &path) {
|
match detect_change_kind(&pwd, &path) {
|
||||||
(ChangeKind::Content, _) => {
|
(ChangeKind::Content, _) => {
|
||||||
|
@ -312,42 +424,9 @@ pub fn serve(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(ChangeKind::Templates, _) => {
|
(ChangeKind::Templates, _) => reload_templates(&mut site, &path),
|
||||||
console::info(&format!("-> Template changed {}", path.display()));
|
(ChangeKind::StaticFiles, p) => copy_static(&site, &path, &p),
|
||||||
if let Some(ref broadcaster) = broadcaster {
|
(ChangeKind::Sass, p) => reload_sass(&site, &path, &p),
|
||||||
// Force refresh
|
|
||||||
rebuild_done_handling(
|
|
||||||
broadcaster,
|
|
||||||
rebuild::after_template_change(&mut site, &path),
|
|
||||||
"/x.js",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(ChangeKind::StaticFiles, p) => {
|
|
||||||
if path.is_file() {
|
|
||||||
console::info(&format!(
|
|
||||||
"-> Static file changes detected {}",
|
|
||||||
path.display()
|
|
||||||
));
|
|
||||||
if let Some(ref broadcaster) = broadcaster {
|
|
||||||
rebuild_done_handling(
|
|
||||||
broadcaster,
|
|
||||||
copy_file(&path, &site.output_path, &site.static_path),
|
|
||||||
&p.to_string_lossy(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(ChangeKind::Sass, p) => {
|
|
||||||
console::info(&format!("-> Sass file changed {}", path.display()));
|
|
||||||
if let Some(ref broadcaster) = broadcaster {
|
|
||||||
rebuild_done_handling(
|
|
||||||
&broadcaster,
|
|
||||||
site.compile_sass(&site.base_path),
|
|
||||||
&p.to_string_lossy(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(ChangeKind::Config, _) => {
|
(ChangeKind::Config, _) => {
|
||||||
console::info("-> Config changed. The whole site will be reloaded. The browser needs to be refreshed to make the changes visible.");
|
console::info("-> Config changed. The whole site will be reloaded. The browser needs to be refreshed to make the changes visible.");
|
||||||
site = create_new_site(
|
site = create_new_site(
|
||||||
|
@ -421,6 +500,18 @@ fn detect_change_kind(pwd: &Path, path: &Path) -> (ChangeKind, PathBuf) {
|
||||||
(change_kind, partial_path)
|
(change_kind, partial_path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if the directory at path contains any file
|
||||||
|
fn is_folder_empty(dir: &Path) -> bool {
|
||||||
|
// Can panic if we don't have the rights I guess?
|
||||||
|
for _ in read_dir(dir).expect("Failed to read a directory to see if it was empty") {
|
||||||
|
// If we get there, that means we have a file
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
Loading…
Reference in a new issue