diff --git a/.gitignore b/.gitignore index 5085055..23e585f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ target .idea/ -components/site/test_site/public +test_site/public docs/public small-blog diff --git a/Cargo.lock b/Cargo.lock index 613da99..f61b97f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1153,7 +1153,6 @@ dependencies = [ "templates 0.1.0", "tera 0.11.5 (registry+https://github.com/rust-lang/crates.io-index)", "utils 0.1.0", - "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1465,6 +1464,7 @@ dependencies = [ "errors 0.1.0", "tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "tera 0.11.5 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/components/front_matter/src/page.rs b/components/front_matter/src/page.rs index ca2c95a..935ba25 100644 --- a/components/front_matter/src/page.rs +++ b/components/front_matter/src/page.rs @@ -94,6 +94,10 @@ pub struct PageFrontMatter { /// Specify a template different from `page.html` to use for that page #[serde(skip_serializing)] pub template: Option, + /// Whether the page is included in the search index + /// Defaults to `true` but is only used if search if explicitly enabled in the config. + #[serde(default, skip_serializing)] + pub in_search_index: bool, /// Any extra parameter present in the front matter #[serde(default)] pub extra: Map, @@ -174,6 +178,7 @@ impl Default for PageFrontMatter { order: None, weight: None, aliases: None, + in_search_index: true, template: None, extra: Map::new(), } diff --git a/components/front_matter/src/section.rs b/components/front_matter/src/section.rs index 4d629ca..64eb27d 100644 --- a/components/front_matter/src/section.rs +++ b/components/front_matter/src/section.rs @@ -48,7 +48,7 @@ pub struct SectionFrontMatter { #[serde(skip_serializing)] pub redirect_to: Option, /// Whether the section content and its pages/subsections are included in the index. - /// Defaults to `true` but is only used if search if explicitely enabled in the config. + /// Defaults to `true` but is only used if search if explicitly enabled in the config. #[serde(skip_serializing)] pub in_search_index: bool, /// Any extra parameter present in the front matter diff --git a/components/site/Cargo.toml b/components/site/Cargo.toml index 55c52e6..5e3a83d 100644 --- a/components/site/Cargo.toml +++ b/components/site/Cargo.toml @@ -6,7 +6,6 @@ authors = ["Vincent Prouillet "] [dependencies] tera = "0.11" glob = "0.2" -walkdir = "2" rayon = "1" serde = "1" serde_derive = "1" diff --git a/components/site/src/lib.rs b/components/site/src/lib.rs index 1a0f6fb..547f91b 100644 --- a/components/site/src/lib.rs +++ b/components/site/src/lib.rs @@ -1,7 +1,6 @@ extern crate tera; extern crate rayon; extern crate glob; -extern crate walkdir; extern crate serde; #[macro_use] extern crate serde_derive; @@ -21,7 +20,7 @@ extern crate content; extern crate tempdir; use std::collections::HashMap; -use std::fs::{remove_dir_all, copy, create_dir_all}; +use std::fs::{remove_dir_all, copy}; use std::mem; use std::path::{Path, PathBuf}; @@ -32,7 +31,7 @@ use sass_rs::{Options as SassOptions, OutputStyle, compile_file}; use errors::{Result, ResultExt}; use config::{Config, get_config}; -use utils::fs::{create_file, create_directory, ensure_directory_exists}; +use utils::fs::{create_file, copy_directory, create_directory, ensure_directory_exists}; use utils::templates::{render_template, rewrite_theme_paths}; use content::{Page, Section, populate_previous_and_next_pages, sort_pages}; use templates::{GUTENBERG_TERA, global_fns, render_redirect_template}; @@ -67,7 +66,7 @@ pub struct Site { pub sections: HashMap, pub tera: Tera, live_reload: bool, - output_path: PathBuf, + pub output_path: PathBuf, pub static_path: PathBuf, pub tags: Option, pub categories: Option, @@ -125,6 +124,11 @@ impl Site { Ok(site) } + /// The index section is ALWAYS at that path + pub fn index_section_path(&self) -> PathBuf { + self.base_path.join("content").join("_index.md") + } + /// What the function name says pub fn enable_live_reload(&mut self) { self.live_reload = true; @@ -198,7 +202,17 @@ impl Site { // Insert a default index section if necessary so we don't need to create // a _index.md to render the index page - let index_path = self.base_path.join("content").join("_index.md"); + let index_path = self.index_section_path(); + if let Some(ref index_section) = self.sections.get(&index_path) { + if self.config.build_search_index && index_section.meta.in_search_index { + bail!( + "You have enabled search in the config but disabled it in the index section: \ + either turn off the search in the config or remote `in_search_index = true` from the \ + section front-matter." + ) + } + } + // Not in else because of borrow checker if !self.sections.contains_key(&index_path) { let mut index_section = Section::default(); index_section.permalink = self.config.make_permalink(""); @@ -409,45 +423,18 @@ impl Site { html } - /// Copy the file at the given path into the public folder - pub fn copy_static_file>(&self, path: P, base_path: &PathBuf) -> Result<()> { - let relative_path = path.as_ref().strip_prefix(base_path).unwrap(); - let target_path = self.output_path.join(relative_path); - if let Some(parent_directory) = target_path.parent() { - create_dir_all(parent_directory)?; - } - copy(path.as_ref(), &target_path)?; - Ok(()) - } - - /// Copy the content of the given folder into the `public` folder - fn copy_static_directory(&self, path: &PathBuf) -> Result<()> { - for entry in WalkDir::new(path).into_iter().filter_map(|e| e.ok()) { - let relative_path = entry.path().strip_prefix(path).unwrap(); - let target_path = self.output_path.join(relative_path); - if entry.path().is_dir() { - if !target_path.exists() { - create_directory(&target_path)?; - } - } else { - let entry_fullpath = self.base_path.join(entry.path()); - self.copy_static_file(entry_fullpath, path)?; - } - } - Ok(()) - } - /// Copy the main `static` folder and the theme `static` folder if a theme is used pub fn copy_static_directories(&self) -> Result<()> { // The user files will overwrite the theme files if let Some(ref theme) = self.config.theme { - self.copy_static_directory( - &self.base_path.join("themes").join(theme).join("static") + copy_directory( + &self.base_path.join("themes").join(theme).join("static"), + &self.output_path )?; } // We're fine with missing static folders if self.static_path.exists() { - self.copy_static_directory(&self.static_path)?; + copy_directory(&self.static_path, &self.output_path)?; } Ok(()) diff --git a/components/site/tests/site.rs b/components/site/tests/site.rs index 598a4f4..516b481 100644 --- a/components/site/tests/site.rs +++ b/components/site/tests/site.rs @@ -445,3 +445,10 @@ fn can_build_rss_feed() { // Next is posts/python.md assert!(file_contains!(public, "rss.xml", "Python in posts")); } + + +#[test] +fn can_build_search_index() { + // TODO: generate an index somehow and check for correctness with + // another one +} diff --git a/components/utils/Cargo.toml b/components/utils/Cargo.toml index 017a1eb..ee330ee 100644 --- a/components/utils/Cargo.toml +++ b/components/utils/Cargo.toml @@ -6,6 +6,7 @@ authors = ["Vincent Prouillet "] [dependencies] errors = { path = "../errors" } tera = "0.11" +walkdir = "2" [dev-dependencies] diff --git a/components/utils/src/fs.rs b/components/utils/src/fs.rs index 7b5381c..06cd80c 100644 --- a/components/utils/src/fs.rs +++ b/components/utils/src/fs.rs @@ -1,9 +1,12 @@ use std::io::prelude::*; -use std::fs::{File, create_dir_all, read_dir}; +use std::fs::{File, create_dir_all, read_dir, copy}; use std::path::{Path, PathBuf}; +use walkdir::WalkDir; + use errors::{Result, ResultExt}; + /// Create a file with the content given pub fn create_file(path: &Path, content: &str) -> Result<()> { let mut file = File::create(&path)?; @@ -60,6 +63,36 @@ pub fn find_related_assets(path: &Path) -> Vec { assets } +/// Copy a file but takes into account where to start the copy as +/// there might be folders we need to create on the way +pub fn copy_file(src: &Path, dest: &PathBuf, base_path: &PathBuf) -> Result<()> { + let relative_path = src.strip_prefix(base_path).unwrap(); + let target_path = dest.join(relative_path); + + if let Some(parent_directory) = target_path.parent() { + create_dir_all(parent_directory)?; + } + + copy(src, target_path)?; + Ok(()) +} + +pub fn copy_directory(src: &PathBuf, dest: &PathBuf) -> Result<()> { + for entry in WalkDir::new(src).into_iter().filter_map(|e| e.ok()) { + let relative_path = entry.path().strip_prefix(src).unwrap(); + let target_path = dest.join(relative_path); + + if entry.path().is_dir() { + if !target_path.exists() { + create_directory(&target_path)?; + } + } else { + copy_file(entry.path(), dest, src)?; + } + } + Ok(()) +} + #[cfg(test)] mod tests { use std::fs::File; diff --git a/components/utils/src/lib.rs b/components/utils/src/lib.rs index 6b447f2..b529aa4 100644 --- a/components/utils/src/lib.rs +++ b/components/utils/src/lib.rs @@ -4,6 +4,7 @@ extern crate errors; #[cfg(test)] extern crate tempdir; extern crate tera; +extern crate walkdir; pub mod fs; pub mod site; diff --git a/src/cmd/serve.rs b/src/cmd/serve.rs index edf6806..67486d6 100644 --- a/src/cmd/serve.rs +++ b/src/cmd/serve.rs @@ -38,6 +38,7 @@ use ctrlc; use site::Site; use errors::{Result, ResultExt}; +use utils::fs::copy_file; use console; use rebuild; @@ -207,7 +208,7 @@ pub fn serve(interface: &str, port: &str, output_dir: &str, base_url: &str, conf (ChangeKind::StaticFiles, p) => { if path.is_file() { console::info(&format!("-> Static file changes detected {}", path.display())); - rebuild_done_handling(&broadcaster, site.copy_static_file(&path, &site.static_path), &p); + rebuild_done_handling(&broadcaster, copy_file(&path, &site.output_path, &site.static_path), &p); } }, (ChangeKind::Sass, p) => {