summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--riki.md9
-rw-r--r--src/page.rs6
-rw-r--r--src/site.rs59
-rw-r--r--src/util.rs25
4 files changed, 81 insertions, 18 deletions
diff --git a/riki.md b/riki.md
index 14be721..4eb6e7f 100644
--- a/riki.md
+++ b/riki.md
@@ -378,16 +378,19 @@ given file site/dir/foo/child.mdwn from empty
given file site/dir/foo/child/grandchild.mdwn from empty
when I run riki build --plain-body site output
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="/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""
~~~
+Note the uppercase link to the `child` page in the test page below.
+
~~~{#foo .file .markdown}
[[/absolute]]
[[sibling]]
[[child]]
[[child/grandchild]]
+[[CHILD]]
~~~
## Wiki links to pages that don't exist
diff --git a/src/page.rs b/src/page.rs
index 8f7c775..189f724 100644
--- a/src/page.rs
+++ b/src/page.rs
@@ -1,6 +1,7 @@
use crate::error::SiteError;
use crate::html::{parse, Content, Element, ElementTag, HtmlPage};
use crate::site::Site;
+use crate::util::join_subpath;
use crate::wikitext::{Snippet, WikitextParser};
use log::{info, trace};
use std::path::{Path, PathBuf};
@@ -22,6 +23,7 @@ impl WikitextPage {
.strip_prefix(&srcdir)
.unwrap_or_else(|_| panic!("get stem from {}", filename.display()))
.with_extension("");
+ let absolute = Path::new("/").join(&relative);
let name = relative
.file_name()
.unwrap_or_else(|| panic!("get filename from {}", relative.display()))
@@ -29,7 +31,7 @@ impl WikitextPage {
.to_string();
let data = std::fs::read(filename).map_err(|e| SiteError::FileRead(filename.into(), e))?;
let wikitext = String::from_utf8(data).map_err(|e| SiteError::Utf8(filename.into(), e))?;
- let meta = MetaBuilder::default().name(name).path(relative).build();
+ let meta = MetaBuilder::default().name(name).path(absolute).build();
Ok(Self::new(meta, wikitext))
}
@@ -133,7 +135,7 @@ impl PageMeta {
}
pub fn destination_filename(&self, destdir: &Path) -> PathBuf {
- destdir.join(&self.path).with_extension("html")
+ join_subpath(destdir, &self.path).with_extension("html")
}
pub fn name(&self) -> &str {
diff --git a/src/site.rs b/src/site.rs
index 9bfa2bd..afdc4d7 100644
--- a/src/site.rs
+++ b/src/site.rs
@@ -2,7 +2,7 @@ use crate::error::SiteError;
use crate::page::{MarkdownPage, UnprocessedPage, WikitextPage};
use crate::wikitext::WikitextParser;
use log::{info, trace};
-use std::collections::HashSet;
+use std::collections::HashMap;
use std::path::{Path, PathBuf};
use walkdir::WalkDir;
@@ -14,7 +14,7 @@ pub struct Site {
parser: WikitextParser,
srcdir: PathBuf,
destdir: PathBuf,
- pages: HashSet<PathBuf>,
+ pages: PageSet,
}
impl Site {
@@ -30,7 +30,7 @@ impl Site {
parser: WikitextParser::default(),
srcdir: srcdir.as_ref().into(),
destdir: destdir.as_ref().into(),
- pages: HashSet::new(),
+ pages: PageSet::default(),
}
}
@@ -48,7 +48,7 @@ impl Site {
pub fn add_wikitextpage(&mut self, page: WikitextPage) {
info!("add wikitext page {}", page.meta().path().display());
- self.pages.insert(page.meta().path().to_path_buf());
+ self.pages.insert(&page);
self.wikitext_pages.push(page);
}
@@ -141,29 +141,52 @@ impl Site {
fn resolve_helper(&self, page: &Path, target: &Path) -> Result<PathBuf, SiteError> {
// Is target absolute?
if target.starts_with("/") {
- return Ok(target.to_path_buf());
+ if let Some(path) = self.pages.get(target) {
+ return Ok(path.into());
+ } else {
+ return Err(SiteError::PageMissing(page.into(), target.into()));
+ }
}
// Does a sub-page exist?
let path = page.join(target);
- if self.have_page(path.as_path()) {
- return Ok(path);
+ if let Some(path) = self.pages.get(&path) {
+ return Ok(path.into());
}
// Does a sibling exist?
if let Some(parent) = page.parent() {
let path = parent.join(target);
- if self.have_page(path.as_path()) {
- return Ok(path);
+ if let Some(path) = self.pages.get(path.as_path()) {
+ return Ok(path.into());
}
}
// Nothing else worked, so make the target absolute.
Err(SiteError::PageMissing(page.into(), target.into()))
}
+}
+
+#[derive(Default)]
+struct PageSet {
+ map: HashMap<String, PathBuf>,
+}
+
+impl PageSet {
+ fn insert(&mut self, page: &WikitextPage) {
+ let path = page.meta().path();
+ let key = Self::normalize(path);
+ self.map.insert(key, path.into());
+ }
+
+ fn get(&self, path: &Path) -> Option<&Path> {
+ self.map.get(&Self::normalize(path)).map(|x| x.as_ref())
+ }
- fn have_page(&self, path: &Path) -> bool {
- self.pages.contains(path)
+ fn normalize(path: &Path) -> String {
+ path.to_str()
+ .expect("path is UTF8")
+ .to_lowercase()
}
}
@@ -186,7 +209,8 @@ mod test {
#[test]
fn absolute_link_resolves_to_absolute() {
- let site = Site::new(".", ".");
+ let mut site = Site::new(".", ".");
+ site.add_wikitextpage(page("/yo/yoyo"));
assert_eq!(
site.resolve("/foo/bar", "/yo/yoyo").unwrap(),
Path::new("/yo/yoyo")
@@ -217,6 +241,17 @@ mod test {
}
#[test]
+ fn link_using_other_casing_is_resolved() {
+ 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")
+ );
+ }
+
+ #[test]
fn link_to_sublpage_resolves_to_it() {
let mut site = Site::new(".", ".");
site.add_wikitextpage(page("/foo/bar/yo"));
diff --git a/src/util.rs b/src/util.rs
index e9b82f3..ec139cd 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -1,6 +1,6 @@
use crate::error::SiteError;
use log::{debug, trace};
-use std::path::{Path, PathBuf};
+use std::path::{Component, Path, PathBuf};
pub fn canonicalize(path: &Path) -> Result<PathBuf, SiteError> {
path.canonicalize()
@@ -34,3 +34,26 @@ pub fn copy_file_from_source(filename: &Path, output: &Path) -> Result<(), SiteE
Ok(())
}
+
+pub fn join_subpath<P: AsRef<Path>>(parent: P, sub: P) -> PathBuf {
+ let sub: PathBuf = sub.as_ref()
+ .components()
+ .filter(|c| *c != Component::RootDir)
+ .collect();
+ parent.as_ref().join(sub)
+}
+
+#[cfg(test)]
+mod test {
+ use super::{join_subpath, PathBuf};
+
+ #[test]
+ fn joins_relative() {
+ assert_eq!(join_subpath("foo", "bar"), PathBuf::from("foo/bar"));
+ }
+
+ #[test]
+ fn joins_absolute() {
+ assert_eq!(join_subpath("foo", "/bar"), PathBuf::from("foo/bar"));
+ }
+}