diff options
Diffstat (limited to 'src/collect_files.rs')
-rw-r--r-- | src/collect_files.rs | 57 |
1 files changed, 51 insertions, 6 deletions
diff --git a/src/collect_files.rs b/src/collect_files.rs index 9c7ac24..b0e24ed 100644 --- a/src/collect_files.rs +++ b/src/collect_files.rs @@ -9,6 +9,7 @@ pub struct Website { pub name: String, pub config: HashMap<String, String>, pub pages: Vec<Page>, + pub redirects: Vec<Redirect>, pub static_files: Vec<StaticItem>, pub static_dirs: Vec<StaticItem>, } @@ -31,10 +32,30 @@ pub struct Heading { } pub struct StaticItem { - pub full_url: String, // Safe full URL, with extension - pub source_path: PathBuf, // Absolute path to source file + pub full_url: String, // Safe full URL, with extension + pub source_path: PathBuf, // Absolute path to source file +} + +pub struct Redirect { + pub name: String, // Display name of this redirect + pub full_url: String, // Safe full URL, no extension + pub parents: Vec<String>, // Parent directory components, unsafe + pub parent_url: String, // Base URL for relative redirects + pub redirect: String, // Page to redirect to, as an internal link } +pub trait LinkFrom { + fn name(&self) -> &str; + fn parent_url(&self) -> &str; + fn parents(&self) -> &[String]; + fn root(&self) -> String { + let mut root = String::new(); + for _ in self.parents() { + root.push_str("../"); + } + return root; + } +} impl Page { @@ -47,12 +68,24 @@ impl Page { } } +impl LinkFrom for Page { + fn name(&self) -> &str { &self.name } + fn parent_url(&self) -> &str { &self.parent_url } + fn parents(&self) -> &[String] { &self.parents } +} + +impl LinkFrom for Redirect { + fn name(&self) -> &str { &self.name } + fn parent_url(&self) -> &str { &self.parent_url } + fn parents(&self) -> &[String] { &self.parents } +} impl Website { pub fn from_path(path: &Path) -> Self { let mut new = Self { pages: Vec::new(), + redirects: Vec::new(), static_files: Vec::new(), static_dirs: Vec::new(), name: match Entry::from_path(path) { @@ -189,6 +222,18 @@ impl Website { }); } }, + "redirect" => { + let mut full_url = String::new(); + for parent in &parents { + full_url.push_str(&make_url_safe(parent)); + full_url.push('/'); + } + let parent_url = full_url.clone(); + full_url.push_str(&name_url); + let redirect = std::fs::read_to_string(&source_path) + .unwrap().trim().to_string(); + self.redirects.push(Redirect { name, full_url, parents, parent_url, redirect }); + } _ => { let mut parent_url = String::new(); for parent in &parents { @@ -205,7 +250,7 @@ impl Website { // Ext is extension without a dot. // Checks if a relative link to an internal page name can be reached from // the current page, and returns a resolved absolute link to the page with extension. - pub fn has_page(&self, from: &Page, path: &str, ext: &str) -> Option<String> { + pub fn has_page(&self, from: &impl LinkFrom, path: &str, ext: &str) -> Option<String> { // Remove heading fragment and file extension. let (path, heading) = match path.rsplit_once('#') { Some((path, heading)) => match heading.is_empty() { @@ -217,7 +262,7 @@ impl Website { let mut path = path.strip_suffix(&format!(".{ext}")).unwrap_or(path).to_string(); // Attach parent if not an absolute path. if !path.starts_with('/') { - path = format!("{}{path}", from.parent_url); + path = format!("{}{path}", from.parent_url()); } // Iteratively collapse ".." segments. @@ -239,12 +284,12 @@ impl Website { break; } // Find page with this path in website. - let path = segments.join("/"); + let path = make_url_safe(&segments.join("/")); for page in &self.pages { if page.full_url == path { if let Some(heading) = heading { if !page.headings.iter().any(|h| h.url == make_url_safe(heading)) { - warn!("Page {:?} contains link to nonexistent heading {heading:?} on page {path:?}", from.name); + warn!("Page {:?} contains link to nonexistent heading {heading:?} on page {path:?}", from.name()); } } let root = from.root(); |