diff options
author | Lars Wirzenius <liw@liw.fi> | 2022-07-20 20:58:19 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2022-07-20 20:58:19 +0300 |
commit | a8dfe6639da061e14b4a56e0d04ebeeb5d34d0e9 (patch) | |
tree | 0082cfc742c6d0465075797bfbfbd96021cf75eb | |
parent | f4c74c6a2eb3b1222ad0b0ae48fb8637522210a4 (diff) | |
download | riki-a8dfe6639da061e14b4a56e0d04ebeeb5d34d0e9.tar.gz |
feat! linking to a page that doesn't exist is an error
On a user-editable wiki, it is useful to allow links to targets that
don't exist. In a static site generator, not.
Sponsored-by: author
-rw-r--r-- | riki.md | 15 | ||||
-rw-r--r-- | src/error.rs | 3 | ||||
-rw-r--r-- | src/site.rs | 54 |
3 files changed, 56 insertions, 16 deletions
@@ -381,7 +381,6 @@ then file output/dir/foo.html contains "href="/absolute"" then file output/dir/foo.html contains "href="dir/sibling"" then file output/dir/foo.html contains "href="dir/foo/child"" then file output/dir/foo.html contains "href="dir/foo/child/grandchild"" -then file output/dir/foo.html contains "href="/missing" ~~~ ~~~{#foo .file .markdown} @@ -389,6 +388,20 @@ then file output/dir/foo.html contains "href="/missing" [[sibling]] [[child]] [[child/grandchild]] +~~~ + +## Wiki links to pages that don't exist + +_Requirement: Linking to a page that doesn't exist is an error._ + +~~~scenario +given an installed riki +given file site/dir/foo.mdwn from badlink +when I try to run riki build --plain-body site output +then command fails +~~~ + +~~~{#badlink .file .markdown} [[missing]] ~~~ diff --git a/src/error.rs b/src/error.rs index faaaaa8..fa8ddf2 100644 --- a/src/error.rs +++ b/src/error.rs @@ -43,4 +43,7 @@ pub enum SiteError { #[error("directive {0} is missing required argument {1}")] DirectiveUnknownArg(String, String), + + #[error("link to missing page {1} on {0}")] + PageMissing(PathBuf, PathBuf), } diff --git a/src/site.rs b/src/site.rs index c1c7249..9bfa2bd 100644 --- a/src/site.rs +++ b/src/site.rs @@ -128,7 +128,7 @@ impl Site { pub fn resolve<P: AsRef<Path>>(&self, page: P, target: P) -> Result<PathBuf, SiteError> { let page = page.as_ref(); let target = target.as_ref(); - let resolved = self.resolve_helper(page, target); + let resolved = self.resolve_helper(page, target)?; trace!( "resolve: page={}, target={} -> {}", page.display(), @@ -138,28 +138,28 @@ impl Site { Ok(resolved) } - fn resolve_helper(&self, page: &Path, target: &Path) -> PathBuf { + fn resolve_helper(&self, page: &Path, target: &Path) -> Result<PathBuf, SiteError> { // Is target absolute? if target.starts_with("/") { - return target.to_path_buf(); + return Ok(target.to_path_buf()); } // Does a sub-page exist? let path = page.join(target); if self.have_page(path.as_path()) { - return path; + return Ok(path); } // Does a sibling exist? if let Some(parent) = page.parent() { let path = parent.join(target); if self.have_page(path.as_path()) { - return path; + return Ok(path); } } // Nothing else worked, so make the target absolute. - PathBuf::from("/").join(target) + Err(SiteError::PageMissing(page.into(), target.into())) } fn have_page(&self, path: &Path) -> bool { @@ -169,7 +169,7 @@ impl Site { #[cfg(test)] mod test { - use super::{Site, WikitextPage}; + use super::{Site, SiteError, WikitextPage}; use crate::page::MetaBuilder; use std::path::{Path, PathBuf}; @@ -187,13 +187,22 @@ mod test { #[test] fn absolute_link_resolves_to_absolute() { let site = Site::new(".", "."); - assert_eq!(site.resolve("/foo/bar", "/yo/yoyo").unwrap(), Path::new("/yo/yoyo")); + assert_eq!( + site.resolve("/foo/bar", "/yo/yoyo").unwrap(), + Path::new("/yo/yoyo") + ); } #[test] - fn link_to_missing_resolves_to_absolute() { + fn link_to_missing_is_an_error() { let site = Site::new(".", "."); - assert_eq!(site.resolve("/foo/bar", "yo").unwrap(), Path::new("/yo")); + match site.resolve("/foo/bar", "yo") { + Err(SiteError::PageMissing(page, target)) => { + assert_eq!(target, PathBuf::from("yo")); + assert_eq!(page, PathBuf::from("/foo/bar")); + } + _ => panic!("unexpected success"), + } } #[test] @@ -201,7 +210,10 @@ mod test { let mut site = Site::new(".", "."); site.add_wikitextpage(page("/foo/yo")); site.process().unwrap(); - assert_eq!(site.resolve("/foo/bar", "yo").unwrap(), Path::new("/foo/yo")); + assert_eq!( + site.resolve("/foo/bar", "yo").unwrap(), + Path::new("/foo/yo") + ); } #[test] @@ -209,7 +221,10 @@ mod test { let mut site = Site::new(".", "."); site.add_wikitextpage(page("/foo/bar/yo")); site.process().unwrap(); - assert_eq!(site.resolve("/foo/bar", "yo").unwrap(), Path::new("/foo/bar/yo")); + assert_eq!( + site.resolve("/foo/bar", "yo").unwrap(), + Path::new("/foo/bar/yo") + ); } #[test] @@ -218,14 +233,23 @@ mod test { site.add_wikitextpage(page("/foo/bar/yo")); site.add_wikitextpage(page("/foo/yo")); site.process().unwrap(); - assert_eq!(site.resolve("/foo/bar", "yo").unwrap(), Path::new("/foo/bar/yo")); + assert_eq!( + site.resolve("/foo/bar", "yo").unwrap(), + Path::new("/foo/bar/yo") + ); } #[test] - fn link_to_unrelated_subpage_resolves_absolute() { + fn link_to_unrelated_subpage_is_an_error() { let mut site = Site::new(".", "."); site.process().unwrap(); - assert_eq!(site.resolve("/foo/bar", "yo/yoyo").unwrap(), Path::new("/yo/yoyo")); + match site.resolve("/foo/bar", "yo/yoyo") { + Err(SiteError::PageMissing(page, target)) => { + assert_eq!(target, PathBuf::from("yo/yoyo")); + assert_eq!(page, PathBuf::from("/foo/bar")); + } + _ => panic!("unexpected success"), + } } #[test] |