From dde9af3efd4fbbe9a882b5b1515cf09d4989df69 Mon Sep 17 00:00:00 2001 From: Vincent Prouillet Date: Sun, 12 Mar 2017 12:54:57 +0900 Subject: [PATCH] Copy assets found in content folders --- README.md | 1 + src/page.rs | 44 ++++++++++++++++++++++++++++++++++++-------- src/site.rs | 5 +++++ 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index be241c9d..67f04810 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ Gallery at https://tmtheme-editor.herokuapp.com/#!/editor/theme/Agola%20Dark # TODO: +- find a way to add tests - syntax highlighting - pass a --config arg to the CLI to change from `config.toml` - have verbosity levels with a `verbosity` config variable with a default diff --git a/src/page.rs b/src/page.rs index 5863ddeb..44d1fb49 100644 --- a/src/page.rs +++ b/src/page.rs @@ -1,8 +1,8 @@ /// A page, can be a blog post or a basic page use std::cmp::Ordering; -use std::fs::File; +use std::fs::{File, read_dir}; use std::io::prelude::*; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::result::Result as StdResult; @@ -21,6 +21,27 @@ lazy_static! { static ref PAGE_RE: Regex = Regex::new(r"^\n?\+\+\+\n((?s).*(?-s))\+\+\+\n((?s).*(?-s))$").unwrap(); } +/// Looks into the current folder for the path and see if there's anything that is not a .md +/// file. Those will be copied next to the rendered .html file +fn find_related_assets(path: &Path) -> Vec { + let mut assets = vec![]; + + for entry in read_dir(path.parent().unwrap()).unwrap().filter_map(|e| e.ok()) { + let entry_path = entry.path(); + if entry_path.is_file() { + match entry_path.extension() { + Some(e) => match e.to_str() { + Some("md") => continue, + _ => assets.push(entry_path.to_path_buf()), + }, + None => continue, + } + } + } + + assets +} + #[derive(Clone, Debug, PartialEq, Deserialize)] pub struct Page { @@ -38,6 +59,9 @@ pub struct Page { /// The actual content of the page, in markdown #[serde(skip_serializing)] pub raw_content: String, + /// All the non-md files we found next to the .md file + #[serde(skip_serializing)] + pub assets: Vec, /// The HTML rendered of the page pub content: String, /// The front matter meta-data @@ -69,6 +93,7 @@ impl Page { filename: "".to_string(), sections: vec![], raw_content: "".to_string(), + assets: vec![], content: "".to_string(), slug: "".to_string(), url: "".to_string(), @@ -80,7 +105,7 @@ impl Page { } } - // Get word count and estimated reading time + /// Get word count and estimated reading time pub fn get_reading_analytics(&self) -> (usize, usize) { // Only works for latin language but good enough for a start let word_count: usize = self.raw_content.split_whitespace().count(); @@ -90,9 +115,9 @@ impl Page { (word_count, (word_count / 200)) } - // Parse a page given the content of the .md file - // Files without front matter or with invalid front matter are considered - // erroneous + /// Parse a page given the content of the .md file + /// Files without front matter or with invalid front matter are considered + /// erroneous pub fn parse(filepath: &str, content: &str, config: &Config) -> Result { // 1. separate front matter from content if !PAGE_RE.is_match(content) { @@ -169,6 +194,7 @@ impl Page { Ok(page) } + /// Read and parse a .md file into a Page struct pub fn from_file>(path: P, config: &Config) -> Result { let path = path.as_ref(); @@ -178,8 +204,10 @@ impl Page { .read_to_string(&mut content)?; // Remove the content string from name - // Maybe get a path as an arg instead and use strip_prefix? - Page::parse(&path.strip_prefix("content").unwrap().to_string_lossy(), &content, config) + let mut page = Page::parse(&path.strip_prefix("content").unwrap().to_string_lossy(), &content, config)?; + page.assets = find_related_assets(&path); + Ok(page) + } /// Renders the page using the default layout, unless specified in front-matter diff --git a/src/site.rs b/src/site.rs index dd433d9d..5931e4a7 100644 --- a/src/site.rs +++ b/src/site.rs @@ -192,6 +192,11 @@ impl Site { // Finally, create a index.html file there with the page rendered let output = page.render_html(&self.templates, &self.config)?; create_file(current_path.join("index.html"), &self.inject_livereload(output))?; + // Copy any asset we found previously into the same directory as the index.html + for asset in &page.assets { + let asset_path = asset.as_path(); + copy(&asset_path, ¤t_path.join(asset_path.file_name().unwrap()))?; + } pages.push(page); if let Some(ref category) = page.meta.category {