Add a FileInfo struct to hold some common data about the files
This commit is contained in:
parent
d9ed7df118
commit
056bf55881
|
@ -85,7 +85,7 @@ pub fn after_content_change(site: &mut Site, path: &Path) -> Result<()> {
|
|||
// A section was deleted, many things can be impacted:
|
||||
// - the pages of the section are becoming orphans
|
||||
// - any page that was referencing the section (index, etc)
|
||||
let relative_path = site.sections[path].relative_path.clone();
|
||||
let relative_path = site.sections[path].file.relative.clone();
|
||||
// Remove the link to it and the section itself from the Site
|
||||
site.permalinks.remove(&relative_path);
|
||||
site.sections.remove(path);
|
||||
|
@ -94,7 +94,7 @@ pub fn after_content_change(site: &mut Site, path: &Path) -> Result<()> {
|
|||
// A page was deleted, many things can be impacted:
|
||||
// - the section the page is in
|
||||
// - any page that was referencing the section (index, etc)
|
||||
let relative_path = site.pages[path].relative_path.clone();
|
||||
let relative_path = site.pages[path].file.relative.clone();
|
||||
site.permalinks.remove(&relative_path);
|
||||
if let Some(p) = site.pages.remove(path) {
|
||||
if p.meta.has_tags() || p.meta.category.is_some() {
|
||||
|
@ -172,7 +172,7 @@ pub fn after_content_change(site: &mut Site, path: &Path) -> Result<()> {
|
|||
},
|
||||
PageChangesNeeded::Sort => {
|
||||
let section_path = match site.find_parent_section(&site.pages[path]) {
|
||||
Some(s) => s.file_path.clone(),
|
||||
Some(s) => s.file.path.clone(),
|
||||
None => continue // Do nothing if it's an orphan page
|
||||
};
|
||||
site.populate_sections();
|
||||
|
|
116
src/content/file_info.rs
Normal file
116
src/content/file_info.rs
Normal file
|
@ -0,0 +1,116 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// Takes a full path to a file and returns only the components after the first `content` directory
|
||||
/// Will not return the filename as last component
|
||||
pub fn find_content_components<P: AsRef<Path>>(path: P) -> Vec<String> {
|
||||
let path = path.as_ref();
|
||||
let mut is_in_content = false;
|
||||
let mut components = vec![];
|
||||
|
||||
for section in path.parent().unwrap().components() {
|
||||
let component = section.as_ref().to_string_lossy();
|
||||
|
||||
if is_in_content {
|
||||
components.push(component.to_string());
|
||||
continue;
|
||||
}
|
||||
|
||||
if component == "content" {
|
||||
is_in_content = true;
|
||||
}
|
||||
}
|
||||
|
||||
components
|
||||
}
|
||||
|
||||
/// Struct that contains all the information about the actual file
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct FileInfo {
|
||||
/// The full path to the .md file
|
||||
pub path: PathBuf,
|
||||
/// The name of the .md file without the extension, always `_index` for sections
|
||||
pub name: String,
|
||||
/// The .md path, starting from the content directory, with `/` slashes
|
||||
pub relative: String,
|
||||
/// Path of the directory containing the .md file
|
||||
pub parent: PathBuf,
|
||||
/// Path of the grand parent directory for that file. Only used in sections to find subsections.
|
||||
pub grand_parent: Option<PathBuf>,
|
||||
/// The folder names to this section file, starting from the `content` directory
|
||||
/// For example a file at content/kb/solutions/blabla.md will have 2 components:
|
||||
/// `kb` and `solutions`
|
||||
pub components: Vec<String>,
|
||||
}
|
||||
|
||||
impl FileInfo {
|
||||
pub fn new_page(path: &Path) -> FileInfo {
|
||||
let file_path = path.to_path_buf();
|
||||
let mut parent = file_path.parent().unwrap().to_path_buf();
|
||||
let name = path.file_stem().unwrap().to_string_lossy().to_string();
|
||||
let mut components = find_content_components(&file_path);
|
||||
let relative = format!("{}/{}.md", components.join("/"), name);
|
||||
|
||||
// If we have a folder with an asset, don't consider it as a component
|
||||
if !components.is_empty() && name == "index" {
|
||||
components.pop();
|
||||
// also set parent_path to grandparent instead
|
||||
parent = parent.parent().unwrap().to_path_buf();
|
||||
}
|
||||
|
||||
FileInfo {
|
||||
path: file_path,
|
||||
// We don't care about grand parent for pages
|
||||
grand_parent: None,
|
||||
parent,
|
||||
name,
|
||||
components,
|
||||
relative,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_section(path: &Path) -> FileInfo {
|
||||
let parent = path.parent().unwrap().to_path_buf();
|
||||
let components = find_content_components(path);
|
||||
let relative = if components.is_empty() {
|
||||
// the index one
|
||||
"_index.md".to_string()
|
||||
} else {
|
||||
format!("{}/_index.md", components.join("/"))
|
||||
};
|
||||
let grand_parent = parent.parent().map(|p| p.to_path_buf());
|
||||
|
||||
FileInfo {
|
||||
path: path.to_path_buf(),
|
||||
parent,
|
||||
grand_parent,
|
||||
name: "_index".to_string(),
|
||||
components,
|
||||
relative,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl Default for FileInfo {
|
||||
fn default() -> FileInfo {
|
||||
FileInfo {
|
||||
path: PathBuf::new(),
|
||||
parent: PathBuf::new(),
|
||||
grand_parent: None,
|
||||
name: String::new(),
|
||||
components: vec![],
|
||||
relative: String::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::find_content_components;
|
||||
|
||||
#[test]
|
||||
fn can_find_content_components() {
|
||||
let res = find_content_components("/home/vincent/code/site/content/posts/tutorials/python.md");
|
||||
assert_eq!(res, ["posts".to_string(), "tutorials".to_string()]);
|
||||
}
|
||||
}
|
|
@ -1,11 +1,9 @@
|
|||
// TODO: move section/page and maybe pagination in this mod
|
||||
// Not sure where pagination stands if I add a render mod
|
||||
|
||||
mod page;
|
||||
mod pagination;
|
||||
mod section;
|
||||
mod sorting;
|
||||
mod utils;
|
||||
mod file_info;
|
||||
|
||||
pub use self::page::{Page};
|
||||
pub use self::section::{Section};
|
||||
|
|
|
@ -13,34 +13,22 @@ use config::Config;
|
|||
use front_matter::{PageFrontMatter, split_page_content};
|
||||
use markdown::markdown_to_html;
|
||||
use utils::{read_file};
|
||||
use content::utils::{find_related_assets, find_content_components, get_reading_analytics};
|
||||
|
||||
use content::utils::{find_related_assets, get_reading_analytics};
|
||||
use content::file_info::FileInfo;
|
||||
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Page {
|
||||
/// All info about the actual file
|
||||
pub file: FileInfo,
|
||||
/// The front matter meta-data
|
||||
pub meta: PageFrontMatter,
|
||||
/// The .md path
|
||||
pub file_path: PathBuf,
|
||||
/// The .md path, starting from the content directory, with / slashes
|
||||
pub relative_path: String,
|
||||
/// The parent directory of the file. Is actually the grand parent directory
|
||||
/// if it's an asset folder
|
||||
pub parent_path: PathBuf,
|
||||
/// The name of the .md file
|
||||
pub file_name: String,
|
||||
/// The directories above our .md file
|
||||
/// for example a file at content/kb/solutions/blabla.md will have 2 components:
|
||||
/// `kb` and `solutions`
|
||||
pub components: Vec<String>,
|
||||
/// The actual content of the page, in markdown
|
||||
pub raw_content: String,
|
||||
/// All the non-md files we found next to the .md file
|
||||
pub assets: Vec<PathBuf>,
|
||||
/// The HTML rendered of the page
|
||||
pub content: String,
|
||||
|
||||
/// The slug of that page.
|
||||
/// First tries to find the slug in the meta and defaults to filename otherwise
|
||||
pub slug: String,
|
||||
|
@ -52,7 +40,6 @@ pub struct Page {
|
|||
/// When <!-- more --> is found in the text, will take the content up to that part
|
||||
/// as summary
|
||||
pub summary: Option<String>,
|
||||
|
||||
/// The previous page, by whatever sorting is used for the index/section
|
||||
pub previous: Option<Box<Page>>,
|
||||
/// The next page, by whatever sorting is used for the index/section
|
||||
|
@ -61,14 +48,12 @@ pub struct Page {
|
|||
|
||||
|
||||
impl Page {
|
||||
pub fn new(meta: PageFrontMatter) -> Page {
|
||||
pub fn new<P: AsRef<Path>>(file_path: P, meta: PageFrontMatter) -> Page {
|
||||
let file_path = file_path.as_ref();
|
||||
|
||||
Page {
|
||||
file: FileInfo::new_page(file_path),
|
||||
meta: meta,
|
||||
file_path: PathBuf::new(),
|
||||
relative_path: String::new(),
|
||||
parent_path: PathBuf::new(),
|
||||
file_name: "".to_string(),
|
||||
components: vec![],
|
||||
raw_content: "".to_string(),
|
||||
assets: vec![],
|
||||
content: "".to_string(),
|
||||
|
@ -85,49 +70,26 @@ impl Page {
|
|||
/// Files without front matter or with invalid front matter are considered
|
||||
/// erroneous
|
||||
pub fn parse(file_path: &Path, content: &str, config: &Config) -> Result<Page> {
|
||||
// 1. separate front matter from content
|
||||
let (meta, content) = split_page_content(file_path, content)?;
|
||||
let mut page = Page::new(meta);
|
||||
page.file_path = file_path.to_path_buf();
|
||||
page.parent_path = page.file_path.parent().unwrap().to_path_buf();
|
||||
let mut page = Page::new(file_path, meta);
|
||||
page.raw_content = content;
|
||||
|
||||
let path = Path::new(file_path);
|
||||
page.file_name = path.file_stem().unwrap().to_string_lossy().to_string();
|
||||
|
||||
page.slug = {
|
||||
if let Some(ref slug) = page.meta.slug {
|
||||
slug.trim().to_string()
|
||||
} else {
|
||||
slugify(page.file_name.clone())
|
||||
slugify(page.file.name.clone())
|
||||
}
|
||||
};
|
||||
page.components = find_content_components(&page.file_path);
|
||||
page.relative_path = format!("{}/{}.md", page.components.join("/"), page.file_name);
|
||||
|
||||
// 4. Find sections
|
||||
// Pages with custom urls exists outside of sections
|
||||
let mut path_set = false;
|
||||
if let Some(ref u) = page.meta.url {
|
||||
page.path = u.trim().to_string();
|
||||
path_set = true;
|
||||
} else {
|
||||
page.path = if page.file.components.is_empty() {
|
||||
page.slug.clone()
|
||||
} else {
|
||||
format!("{}/{}", page.file.components.join("/"), page.slug)
|
||||
};
|
||||
}
|
||||
|
||||
if !page.components.is_empty() {
|
||||
// If we have a folder with an asset, don't consider it as a component
|
||||
if page.file_name == "index" {
|
||||
page.components.pop();
|
||||
// also set parent_path to grandparent instead
|
||||
page.parent_path = page.parent_path.parent().unwrap().to_path_buf();
|
||||
}
|
||||
if !path_set {
|
||||
// Don't add a trailing slash to sections
|
||||
page.path = format!("{}/{}", page.components.join("/"), page.slug);
|
||||
}
|
||||
} else if !path_set {
|
||||
page.path = page.slug.clone();
|
||||
}
|
||||
|
||||
page.permalink = config.make_permalink(&page.path);
|
||||
|
||||
Ok(page)
|
||||
|
@ -140,7 +102,7 @@ impl Page {
|
|||
let mut page = Page::parse(path, &content, config)?;
|
||||
page.assets = find_related_assets(path.parent().unwrap());
|
||||
|
||||
if !page.assets.is_empty() && page.file_name != "index" {
|
||||
if !page.assets.is_empty() && page.file.name != "index" {
|
||||
bail!("Page `{}` has assets ({:?}) but is not named index.md", path.display(), page.assets);
|
||||
}
|
||||
|
||||
|
@ -177,19 +139,15 @@ impl Page {
|
|||
context.add("current_path", &self.path);
|
||||
|
||||
tera.render(&tpl_name, &context)
|
||||
.chain_err(|| format!("Failed to render page '{}'", self.file_path.display()))
|
||||
.chain_err(|| format!("Failed to render page '{}'", self.file.path.display()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Page {
|
||||
fn default() -> Page {
|
||||
Page {
|
||||
file: FileInfo::default(),
|
||||
meta: PageFrontMatter::default(),
|
||||
file_path: PathBuf::new(),
|
||||
relative_path: String::new(),
|
||||
parent_path: PathBuf::new(),
|
||||
file_name: "".to_string(),
|
||||
components: vec![],
|
||||
raw_content: "".to_string(),
|
||||
assets: vec![],
|
||||
content: "".to_string(),
|
||||
|
@ -352,7 +310,7 @@ Hello world
|
|||
);
|
||||
assert!(res.is_ok());
|
||||
let page = res.unwrap();
|
||||
assert_eq!(page.parent_path, path.join("content").join("posts"));
|
||||
assert_eq!(page.file.parent, path.join("content").join("posts"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -145,7 +145,7 @@ impl<'a> Paginator<'a> {
|
|||
}
|
||||
|
||||
site.tera.render(&self.section.get_template_name(), &context)
|
||||
.chain_err(|| format!("Failed to render pager {} of section '{}'", pager.index, self.section.file_path.display()))
|
||||
.chain_err(|| format!("Failed to render pager {} of section '{}'", pager.index, self.section.file.path.display()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ mod tests {
|
|||
if !is_index {
|
||||
s.path = "posts".to_string();
|
||||
s.permalink = "https://vincent.is/posts".to_string();
|
||||
s.components = vec!["posts".to_string()];
|
||||
s.file.components = vec!["posts".to_string()];
|
||||
} else {
|
||||
s.permalink = "https://vincent.is".to_string();
|
||||
}
|
||||
|
|
|
@ -11,21 +11,15 @@ use errors::{Result, ResultExt};
|
|||
use utils::{read_file};
|
||||
use markdown::markdown_to_html;
|
||||
use content::Page;
|
||||
use content::utils::find_content_components;
|
||||
use content::file_info::FileInfo;
|
||||
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Section {
|
||||
/// All info about the actual file
|
||||
pub file: FileInfo,
|
||||
/// The front matter meta-data
|
||||
pub meta: SectionFrontMatter,
|
||||
/// The _index.md full path
|
||||
pub file_path: PathBuf,
|
||||
/// The .md path, starting from the content directory, with / slashes
|
||||
pub relative_path: String,
|
||||
/// Path of the directory containing the _index.md file
|
||||
pub parent_path: PathBuf,
|
||||
/// The folder names from `content` to this section file
|
||||
pub components: Vec<String>,
|
||||
/// The URL path of the page
|
||||
pub path: String,
|
||||
/// The full URL for that page
|
||||
|
@ -47,11 +41,8 @@ impl Section {
|
|||
let file_path = file_path.as_ref();
|
||||
|
||||
Section {
|
||||
file: FileInfo::new_section(file_path),
|
||||
meta: meta,
|
||||
file_path: file_path.to_path_buf(),
|
||||
relative_path: "".to_string(),
|
||||
parent_path: file_path.parent().unwrap().to_path_buf(),
|
||||
components: vec![],
|
||||
path: "".to_string(),
|
||||
permalink: "".to_string(),
|
||||
raw_content: "".to_string(),
|
||||
|
@ -66,16 +57,8 @@ impl Section {
|
|||
let (meta, content) = split_section_content(file_path, content)?;
|
||||
let mut section = Section::new(file_path, meta);
|
||||
section.raw_content = content.clone();
|
||||
section.components = find_content_components(§ion.file_path);
|
||||
section.path = section.components.join("/");
|
||||
section.path = section.file.components.join("/");
|
||||
section.permalink = config.make_permalink(§ion.path);
|
||||
if section.components.is_empty() {
|
||||
// the index one
|
||||
section.relative_path = "_index.md".to_string();
|
||||
} else {
|
||||
section.relative_path = format!("{}/_index.md", section.components.join("/"));
|
||||
}
|
||||
|
||||
Ok(section)
|
||||
}
|
||||
|
||||
|
@ -120,46 +103,36 @@ impl Section {
|
|||
}
|
||||
|
||||
tera.render(&tpl_name, &context)
|
||||
.chain_err(|| format!("Failed to render section '{}'", self.file_path.display()))
|
||||
.chain_err(|| format!("Failed to render section '{}'", self.file.path.display()))
|
||||
}
|
||||
|
||||
/// Is this the index section?
|
||||
pub fn is_index(&self) -> bool {
|
||||
self.components.is_empty()
|
||||
self.file.components.is_empty()
|
||||
}
|
||||
|
||||
/// Returns all the paths for the pages belonging to that section
|
||||
/// Returns all the paths of the pages belonging to that section
|
||||
pub fn all_pages_path(&self) -> Vec<PathBuf> {
|
||||
let mut paths = vec![];
|
||||
paths.extend(self.pages.iter().map(|p| p.file_path.clone()));
|
||||
paths.extend(self.ignored_pages.iter().map(|p| p.file_path.clone()));
|
||||
paths.extend(self.pages.iter().map(|p| p.file.path.clone()));
|
||||
paths.extend(self.ignored_pages.iter().map(|p| p.file.path.clone()));
|
||||
paths
|
||||
}
|
||||
|
||||
/// Whether the page given belongs to that section
|
||||
pub fn is_child_page(&self, page: &Page) -> bool {
|
||||
for p in &self.pages {
|
||||
if p.file_path == page.file_path {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for p in &self.ignored_pages {
|
||||
if p.file_path == page.file_path {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
self.all_pages_path().contains(&page.file.path)
|
||||
}
|
||||
}
|
||||
|
||||
impl ser::Serialize for Section {
|
||||
fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error> where S: ser::Serializer {
|
||||
let mut state = serializer.serialize_struct("section", 7)?;
|
||||
let mut state = serializer.serialize_struct("section", 9)?;
|
||||
state.serialize_field("content", &self.content)?;
|
||||
state.serialize_field("permalink", &self.permalink)?;
|
||||
state.serialize_field("title", &self.meta.title)?;
|
||||
state.serialize_field("description", &self.meta.description)?;
|
||||
state.serialize_field("extra", &self.meta.extra)?;
|
||||
state.serialize_field("path", &format!("/{}", self.path))?;
|
||||
state.serialize_field("permalink", &self.permalink)?;
|
||||
state.serialize_field("pages", &self.pages)?;
|
||||
|
@ -168,15 +141,12 @@ impl ser::Serialize for Section {
|
|||
}
|
||||
}
|
||||
|
||||
/// Used to create a default index section if there is no _index.md in the root content directory
|
||||
impl Default for Section {
|
||||
/// Used to create a default index section if there is no _index.md in the root content directory
|
||||
fn default() -> Section {
|
||||
Section {
|
||||
file: FileInfo::default(),
|
||||
meta: SectionFrontMatter::default(),
|
||||
file_path: PathBuf::new(),
|
||||
relative_path: "".to_string(),
|
||||
parent_path: PathBuf::new(),
|
||||
components: vec![],
|
||||
path: "".to_string(),
|
||||
permalink: "".to_string(),
|
||||
raw_content: "".to_string(),
|
||||
|
|
|
@ -81,13 +81,13 @@ mod tests {
|
|||
fn create_page_with_date(date: &str) -> Page {
|
||||
let mut front_matter = PageFrontMatter::default();
|
||||
front_matter.date = Some(date.to_string());
|
||||
Page::new(front_matter)
|
||||
Page::new("content/hello.md", front_matter)
|
||||
}
|
||||
|
||||
fn create_page_with_order(order: usize) -> Page {
|
||||
let mut front_matter = PageFrontMatter::default();
|
||||
front_matter.order = Some(order);
|
||||
Page::new(front_matter)
|
||||
Page::new("content/hello.md", front_matter)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -32,37 +32,13 @@ pub fn get_reading_analytics(content: &str) -> (usize, usize) {
|
|||
(word_count, (word_count / 200))
|
||||
}
|
||||
|
||||
|
||||
/// Takes a full path to a .md and returns only the components after the first `content` directory
|
||||
/// Will not return the filename as last component
|
||||
pub fn find_content_components<P: AsRef<Path>>(path: P) -> Vec<String> {
|
||||
let path = path.as_ref();
|
||||
let mut is_in_content = false;
|
||||
let mut components = vec![];
|
||||
|
||||
for section in path.parent().unwrap().components() {
|
||||
let component = section.as_ref().to_string_lossy();
|
||||
|
||||
if is_in_content {
|
||||
components.push(component.to_string());
|
||||
continue;
|
||||
}
|
||||
|
||||
if component == "content" {
|
||||
is_in_content = true;
|
||||
}
|
||||
}
|
||||
|
||||
components
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::fs::File;
|
||||
|
||||
use tempdir::TempDir;
|
||||
|
||||
use super::{find_related_assets, find_content_components, get_reading_analytics};
|
||||
use super::{find_related_assets, get_reading_analytics};
|
||||
|
||||
#[test]
|
||||
fn can_find_related_assets() {
|
||||
|
@ -97,10 +73,4 @@ mod tests {
|
|||
assert_eq!(word_count, 2000);
|
||||
assert_eq!(reading_time, 10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_find_content_components() {
|
||||
let res = find_content_components("/home/vincent/code/site/content/posts/tutorials/python.md");
|
||||
assert_eq!(res, ["posts".to_string(), "tutorials".to_string()]);
|
||||
}
|
||||
}
|
||||
|
|
35
src/site.rs
35
src/site.rs
|
@ -93,7 +93,7 @@ impl Site {
|
|||
pub fn get_ignored_pages(&self) -> Vec<PathBuf> {
|
||||
self.sections
|
||||
.values()
|
||||
.flat_map(|s| s.ignored_pages.iter().map(|p| p.file_path.clone()))
|
||||
.flat_map(|s| s.ignored_pages.iter().map(|p| p.file.path.clone()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ impl Site {
|
|||
}
|
||||
|
||||
for page in self.pages.values() {
|
||||
if !pages_in_sections.contains(&page.file_path) {
|
||||
if !pages_in_sections.contains(&page.file.path) {
|
||||
orphans.push(page);
|
||||
}
|
||||
}
|
||||
|
@ -146,8 +146,8 @@ impl Site {
|
|||
self.add_page(path, false)?;
|
||||
}
|
||||
}
|
||||
// Insert a default index section so we don't need to create a _index.md to render
|
||||
// the index page
|
||||
// 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");
|
||||
if !self.sections.contains_key(&index_path) {
|
||||
let mut index_section = Section::default();
|
||||
|
@ -178,8 +178,8 @@ impl Site {
|
|||
/// Returns the previous page struct if there was one
|
||||
pub fn add_page(&mut self, path: &Path, render: bool) -> Result<Option<Page>> {
|
||||
let page = Page::from_file(&path, &self.config)?;
|
||||
self.permalinks.insert(page.relative_path.clone(), page.permalink.clone());
|
||||
let prev = self.pages.insert(page.file_path.clone(), page);
|
||||
self.permalinks.insert(page.file.relative.clone(), page.permalink.clone());
|
||||
let prev = self.pages.insert(page.file.path.clone(), page);
|
||||
|
||||
if render {
|
||||
let mut page = self.pages.get_mut(path).unwrap();
|
||||
|
@ -192,11 +192,11 @@ impl Site {
|
|||
/// Add a section to the site
|
||||
/// The `render` parameter is used in the serve command, when rebuilding a page.
|
||||
/// If `true`, it will also render the markdown for that page
|
||||
/// Returns the previous page struct if there was one
|
||||
/// Returns the previous section struct if there was one
|
||||
pub fn add_section(&mut self, path: &Path, render: bool) -> Result<Option<Section>> {
|
||||
let section = Section::from_file(path, &self.config)?;
|
||||
self.permalinks.insert(section.relative_path.clone(), section.permalink.clone());
|
||||
let prev = self.sections.insert(section.file_path.clone(), section);
|
||||
self.permalinks.insert(section.file.relative.clone(), section.permalink.clone());
|
||||
let prev = self.sections.insert(section.file.path.clone(), section);
|
||||
|
||||
if render {
|
||||
let mut section = self.sections.get_mut(path).unwrap();
|
||||
|
@ -211,7 +211,7 @@ impl Site {
|
|||
pub fn populate_sections(&mut self) {
|
||||
let mut grandparent_paths = HashMap::new();
|
||||
for section in self.sections.values_mut() {
|
||||
if let Some(grand_parent) = section.parent_path.parent() {
|
||||
if let Some(ref grand_parent) = section.file.grand_parent {
|
||||
grandparent_paths.entry(grand_parent.to_path_buf()).or_insert_with(|| vec![]).push(section.clone());
|
||||
}
|
||||
// Make sure the pages of a section are empty since we can call that many times on `serve`
|
||||
|
@ -220,13 +220,14 @@ impl Site {
|
|||
}
|
||||
|
||||
for page in self.pages.values() {
|
||||
if self.sections.contains_key(&page.parent_path.join("_index.md")) {
|
||||
self.sections.get_mut(&page.parent_path.join("_index.md")).unwrap().pages.push(page.clone());
|
||||
let parent_section_path = page.file.parent.join("_index.md");
|
||||
if self.sections.contains_key(&parent_section_path) {
|
||||
self.sections.get_mut(&parent_section_path).unwrap().pages.push(page.clone());
|
||||
}
|
||||
}
|
||||
|
||||
for section in self.sections.values_mut() {
|
||||
match grandparent_paths.get(§ion.parent_path) {
|
||||
match grandparent_paths.get(§ion.file.parent) {
|
||||
Some(paths) => section.subsections.extend(paths.clone()),
|
||||
None => continue,
|
||||
};
|
||||
|
@ -257,7 +258,7 @@ impl Site {
|
|||
self.categories
|
||||
.entry(category.to_string())
|
||||
.or_insert_with(|| vec![])
|
||||
.push(page.file_path.clone());
|
||||
.push(page.file.path.clone());
|
||||
}
|
||||
|
||||
if let Some(ref tags) = page.meta.tags {
|
||||
|
@ -265,7 +266,7 @@ impl Site {
|
|||
self.tags
|
||||
.entry(tag.to_string())
|
||||
.or_insert_with(|| vec![])
|
||||
.push(page.file_path.clone());
|
||||
.push(page.file.path.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -554,7 +555,7 @@ impl Site {
|
|||
fn get_sections_map(&self) -> HashMap<String, Section> {
|
||||
self.sections
|
||||
.values()
|
||||
.map(|s| (s.components.join("/"), s.clone()))
|
||||
.map(|s| (s.file.components.join("/"), s.clone()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -564,7 +565,7 @@ impl Site {
|
|||
let public = self.output_path.clone();
|
||||
|
||||
let mut output_path = public.to_path_buf();
|
||||
for component in §ion.components {
|
||||
for component in §ion.file.components {
|
||||
output_path.push(component);
|
||||
|
||||
if !output_path.exists() {
|
||||
|
|
|
@ -9,7 +9,7 @@ use content::Page;
|
|||
pub fn make_get_page(all_pages: &HashMap<PathBuf, Page>) -> GlobalFn {
|
||||
let mut pages = HashMap::new();
|
||||
for page in all_pages.values() {
|
||||
pages.insert(page.relative_path.clone(), page.clone());
|
||||
pages.insert(page.file.relative.clone(), page.clone());
|
||||
}
|
||||
|
||||
Box::new(move |args| -> Result<Value> {
|
||||
|
|
|
@ -12,7 +12,7 @@ use gutenberg::{Site};
|
|||
|
||||
|
||||
#[test]
|
||||
fn test_can_parse_site() {
|
||||
fn can_parse_site() {
|
||||
let mut path = env::current_dir().unwrap().to_path_buf();
|
||||
path.push("test_site");
|
||||
let mut site = Site::new(&path, "config.toml").unwrap();
|
||||
|
@ -24,7 +24,7 @@ fn test_can_parse_site() {
|
|||
|
||||
// Make sure we remove all the pwd + content from the sections
|
||||
let basic = &site.pages[&posts_path.join("simple.md")];
|
||||
assert_eq!(basic.components, vec!["posts".to_string()]);
|
||||
assert_eq!(basic.file.components, vec!["posts".to_string()]);
|
||||
|
||||
// Make sure the page with a url doesn't have any sections
|
||||
let url_post = &site.pages[&posts_path.join("fixed-url.md")];
|
||||
|
@ -32,7 +32,7 @@ fn test_can_parse_site() {
|
|||
|
||||
// Make sure the article in a folder with only asset doesn't get counted as a section
|
||||
let asset_folder_post = &site.pages[&posts_path.join("with-assets").join("index.md")];
|
||||
assert_eq!(asset_folder_post.components, vec!["posts".to_string()]);
|
||||
assert_eq!(asset_folder_post.file.components, vec!["posts".to_string()]);
|
||||
|
||||
// That we have the right number of sections
|
||||
assert_eq!(site.sections.len(), 6);
|
||||
|
@ -89,7 +89,7 @@ macro_rules! file_contains {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_can_build_site_without_live_reload() {
|
||||
fn can_build_site_without_live_reload() {
|
||||
let mut path = env::current_dir().unwrap().to_path_buf();
|
||||
path.push("test_site");
|
||||
let mut site = Site::new(&path, "config.toml").unwrap();
|
||||
|
@ -131,7 +131,7 @@ fn test_can_build_site_without_live_reload() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_can_build_site_with_live_reload() {
|
||||
fn can_build_site_with_live_reload() {
|
||||
let mut path = env::current_dir().unwrap().to_path_buf();
|
||||
path.push("test_site");
|
||||
let mut site = Site::new(&path, "config.toml").unwrap();
|
||||
|
@ -169,7 +169,7 @@ fn test_can_build_site_with_live_reload() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_can_build_site_with_categories() {
|
||||
fn can_build_site_with_categories() {
|
||||
let mut path = env::current_dir().unwrap().to_path_buf();
|
||||
path.push("test_site");
|
||||
let mut site = Site::new(&path, "config.toml").unwrap();
|
||||
|
@ -221,7 +221,7 @@ fn test_can_build_site_with_categories() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_can_build_site_with_tags() {
|
||||
fn can_build_site_with_tags() {
|
||||
let mut path = env::current_dir().unwrap().to_path_buf();
|
||||
path.push("test_site");
|
||||
let mut site = Site::new(&path, "config.toml").unwrap();
|
||||
|
@ -273,7 +273,7 @@ fn test_can_build_site_with_tags() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_can_build_site_and_insert_anchor_links() {
|
||||
fn can_build_site_and_insert_anchor_links() {
|
||||
let mut path = env::current_dir().unwrap().to_path_buf();
|
||||
path.push("test_site");
|
||||
let mut site = Site::new(&path, "config.toml").unwrap();
|
||||
|
@ -290,7 +290,7 @@ fn test_can_build_site_and_insert_anchor_links() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_can_build_site_with_pagination_for_section() {
|
||||
fn can_build_site_with_pagination_for_section() {
|
||||
let mut path = env::current_dir().unwrap().to_path_buf();
|
||||
path.push("test_site");
|
||||
let mut site = Site::new(&path, "config.toml").unwrap();
|
||||
|
@ -349,7 +349,7 @@ fn test_can_build_site_with_pagination_for_section() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_can_build_site_with_pagination_for_index() {
|
||||
fn can_build_site_with_pagination_for_index() {
|
||||
let mut path = env::current_dir().unwrap().to_path_buf();
|
||||
path.push("test_site");
|
||||
let mut site = Site::new(&path, "config.toml").unwrap();
|
||||
|
|
Loading…
Reference in a new issue