171 lines
4.9 KiB
Rust
171 lines
4.9 KiB
Rust
use std::path::Component;
|
|
use std::path::Path;
|
|
use std::path::PathBuf;
|
|
|
|
use crate::config::Config;
|
|
use crate::context::GlobalSettings;
|
|
use crate::context::RenderBlogPostPage;
|
|
use crate::context::RenderDocumentElement;
|
|
use crate::context::RenderRealFootnoteDefinition;
|
|
use crate::error::CustomError;
|
|
|
|
use super::BlogPost;
|
|
use super::BlogPostPage;
|
|
|
|
pub(crate) fn convert_blog_post_page_to_render_context<D: AsRef<Path>, F: AsRef<Path>>(
|
|
config: &Config,
|
|
output_directory: D,
|
|
output_file: F,
|
|
_post: &BlogPost,
|
|
page: &BlogPostPage,
|
|
) -> Result<RenderBlogPostPage, CustomError> {
|
|
let output_directory = output_directory.as_ref();
|
|
let output_file = output_file.as_ref();
|
|
let css_files = vec![get_web_path(
|
|
config,
|
|
output_directory,
|
|
output_file,
|
|
"main.css",
|
|
)?];
|
|
let js_files = vec![get_web_path(
|
|
config,
|
|
output_directory,
|
|
output_file,
|
|
"blog_post.js",
|
|
)?];
|
|
let global_settings = GlobalSettings::new(page.title.clone(), css_files, js_files);
|
|
let link_to_blog_post = get_web_path(
|
|
config,
|
|
output_directory,
|
|
output_file,
|
|
output_file.strip_prefix(output_directory)?,
|
|
)?;
|
|
|
|
let children = {
|
|
let mut children = Vec::new();
|
|
|
|
for child in page.children.iter() {
|
|
children.push(RenderDocumentElement::new(
|
|
config,
|
|
output_directory,
|
|
output_file,
|
|
child,
|
|
)?);
|
|
}
|
|
|
|
children
|
|
};
|
|
|
|
let footnotes = {
|
|
let mut ret = Vec::new();
|
|
|
|
for footnote in page.footnotes.iter() {
|
|
ret.push(RenderRealFootnoteDefinition::new(
|
|
config,
|
|
output_directory,
|
|
output_file,
|
|
footnote,
|
|
)?);
|
|
}
|
|
|
|
ret
|
|
};
|
|
|
|
let ret = RenderBlogPostPage::new(
|
|
global_settings,
|
|
page.title.clone(),
|
|
Some(link_to_blog_post),
|
|
children,
|
|
footnotes,
|
|
);
|
|
Ok(ret)
|
|
}
|
|
|
|
fn get_web_path<D: AsRef<Path>, F: AsRef<Path>, P: AsRef<Path>>(
|
|
config: &Config,
|
|
output_directory: D,
|
|
containing_file: F,
|
|
path_from_web_root: P,
|
|
) -> Result<String, CustomError> {
|
|
let path_from_web_root = path_from_web_root.as_ref();
|
|
if config.use_relative_paths() {
|
|
let output_directory = output_directory.as_ref();
|
|
let containing_file = containing_file.as_ref();
|
|
let containing_file_relative_to_output_directory =
|
|
containing_file.strip_prefix(output_directory)?;
|
|
let shared_stem = get_shared_steps(
|
|
containing_file_relative_to_output_directory
|
|
.parent()
|
|
.ok_or("File should exist in a folder.")?,
|
|
path_from_web_root
|
|
.parent()
|
|
.ok_or("File should exist in a folder.")?,
|
|
)
|
|
.collect::<PathBuf>();
|
|
// Subtracting 1 from the depth to "remove" the file name.
|
|
let depth_from_shared_stem = containing_file_relative_to_output_directory
|
|
.strip_prefix(&shared_stem)?
|
|
.components()
|
|
.count()
|
|
- 1;
|
|
let final_path = PathBuf::from("../".repeat(depth_from_shared_stem))
|
|
.join(path_from_web_root.strip_prefix(shared_stem)?);
|
|
let final_string = final_path
|
|
.as_path()
|
|
.to_str()
|
|
.map(str::to_string)
|
|
.ok_or("Path should be valid utf-8.")?;
|
|
Ok(final_string)
|
|
} else {
|
|
let web_root = config
|
|
.get_web_root()
|
|
.ok_or("Must either use_relative_paths or set the web_root in the config.")?;
|
|
let final_path = PathBuf::from(web_root).join(path_from_web_root);
|
|
let final_string = final_path
|
|
.as_path()
|
|
.to_str()
|
|
.map(str::to_string)
|
|
.ok_or("Path should be valid utf-8.")?;
|
|
Ok(final_string)
|
|
}
|
|
}
|
|
|
|
fn get_shared_steps<'a>(left: &'a Path, right: &'a Path) -> impl Iterator<Item = Component<'a>> {
|
|
let shared_stem = left
|
|
.components()
|
|
.zip(right.components())
|
|
.take_while(|(l, r)| l == r)
|
|
.map(|(l, _r)| l);
|
|
shared_stem
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_get_shared_steps() {
|
|
assert_eq!(
|
|
get_shared_steps(Path::new(""), Path::new("")).collect::<PathBuf>(),
|
|
PathBuf::from("")
|
|
);
|
|
assert_eq!(
|
|
get_shared_steps(Path::new("foo.txt"), Path::new("foo.txt")).collect::<PathBuf>(),
|
|
PathBuf::from("foo.txt")
|
|
);
|
|
assert_eq!(
|
|
get_shared_steps(Path::new("cat/foo.txt"), Path::new("dog/foo.txt"))
|
|
.collect::<PathBuf>(),
|
|
PathBuf::from("")
|
|
);
|
|
assert_eq!(
|
|
get_shared_steps(
|
|
Path::new("foo/bar/baz/lorem.txt"),
|
|
Path::new("foo/bar/ipsum/dolar.txt")
|
|
)
|
|
.collect::<PathBuf>(),
|
|
PathBuf::from("foo/bar")
|
|
);
|
|
}
|
|
}
|