From 11bfb6836fc12f77ff2fbc993170d81cf4db6b3d Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Mon, 23 Oct 2023 22:38:00 -0400 Subject: [PATCH] Include a self-link for the blog. --- src/blog_post/convert.rs | 40 ++++++++++++++++++++++++++++++--- src/blog_post/render_context.rs | 4 ++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/blog_post/convert.rs b/src/blog_post/convert.rs index baed94d..8a03dd6 100644 --- a/src/blog_post/convert.rs +++ b/src/blog_post/convert.rs @@ -31,8 +31,14 @@ pub(crate) fn convert_blog_post_page_to_render_context, F: AsRef< "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 ret = RenderBlogPostPage::new(global_settings, page.title.clone()); + let ret = RenderBlogPostPage::new(global_settings, page.title.clone(), Some(link_to_blog_post)); Ok(ret) } @@ -46,13 +52,15 @@ fn get_web_path, F: AsRef, P: AsRef>( 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)?; // Subtracting 1 from the depth to "remove" the file name. - let depth_from_web_root = containing_file - .strip_prefix(output_directory)? + let depth_from_web_root = containing_file_relative_to_output_directory .components() .count() - 1; let prefix = "../".repeat(depth_from_web_root); + // TODO: It should be possible to strip some of the "../" components based on whether the path_from_web_root goes down the same path as the containing file. let final_path = PathBuf::from(prefix).join(path_from_web_root); let final_string = final_path .as_path() @@ -73,3 +81,29 @@ fn get_web_path, F: AsRef, P: AsRef>( Ok(final_string) } } + +#[allow(dead_code)] +fn count_shared_steps, B: AsRef>(left: A, right: B) -> usize { + let left = left.as_ref(); + let right = right.as_ref(); + left.components() + .zip(right.components()) + .position(|(l, r)| l != r) + .unwrap_or_else(|| left.components().count()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_count_shared_steps() { + assert_eq!(count_shared_steps("", ""), 0); + assert_eq!(count_shared_steps("foo.txt", "foo.txt"), 1); + assert_eq!(count_shared_steps("cat/foo.txt", "dog/foo.txt"), 0); + assert_eq!( + count_shared_steps("foo/bar/baz/lorem.txt", "foo/bar/ipsum/dolar.txt"), + 2 + ); + } +} diff --git a/src/blog_post/render_context.rs b/src/blog_post/render_context.rs index 8015ece..4085b9d 100644 --- a/src/blog_post/render_context.rs +++ b/src/blog_post/render_context.rs @@ -31,16 +31,20 @@ pub(crate) struct RenderBlogPostPage { /// The title that will be shown visibly on the page. title: Option, + + self_link: Option, } impl RenderBlogPostPage { pub(crate) fn new( global_settings: GlobalSettings, title: Option, + self_link: Option, ) -> RenderBlogPostPage { RenderBlogPostPage { global_settings, title, + self_link, } } }