Generate the minimum relative path by chopping off the shared stem.

This commit is contained in:
Tom Alexander 2023-10-23 23:04:05 -04:00
parent 68cae57f16
commit ab36a60545
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE

View File

@ -55,14 +55,23 @@ fn get_web_path<D: AsRef<Path>, F: AsRef<Path>, P: AsRef<Path>>(
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_web_root = containing_file_relative_to_output_directory
let depth_from_shared_stem = containing_file_relative_to_output_directory
.strip_prefix(&shared_stem)?
.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_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()
@ -83,42 +92,19 @@ fn get_web_path<D: AsRef<Path>, F: AsRef<Path>, P: AsRef<Path>>(
}
}
#[allow(dead_code)]
fn count_shared_steps<A: AsRef<Path>, B: AsRef<Path>>(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())
}
#[allow(dead_code)]
fn get_shared_steps<'a>(left: &'a Path, right: &'a Path) -> impl Iterator<Item = Component<'a>> {
let foo: Vec<Component<'_>> = left
let shared_stem = left
.components()
.zip(right.components())
.take_while(|(l, r)| l == r)
.map(|(l, _r)| l)
.collect();
foo.into_iter()
.map(|(l, _r)| l);
shared_stem
}
#[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
);
}
#[test]
fn test_get_shared_steps() {
assert_eq!(