diff options
Diffstat (limited to 'src/site.rs')
-rw-r--r-- | src/site.rs | 104 |
1 files changed, 67 insertions, 37 deletions
diff --git a/src/site.rs b/src/site.rs index cfd5017..5196b5c 100644 --- a/src/site.rs +++ b/src/site.rs @@ -44,9 +44,8 @@ pub struct Site { patterns: TokenPatterns, shortcuts: HashMap<String, Shortcut>, name_builder: NameBuilder, - pages: Vec<Page>, - markdown_pages: Vec<MarkdownPage>, - pages_that_will_exist: PageSet, + unprocessed_pages: PageSet<Page>, + markdown_pages: PageSet<MarkdownPage>, files: Names, } @@ -60,11 +59,10 @@ impl Site { { Self { name_builder: NameBuilder::new(srcdir.as_ref(), destdir.as_ref()), - pages: vec![], - markdown_pages: vec![], + unprocessed_pages: PageSet::default(), + markdown_pages: PageSet::default(), files: Names::default(), patterns: TokenPatterns::default(), - pages_that_will_exist: PageSet::default(), shortcuts: HashMap::new(), } } @@ -91,7 +89,6 @@ impl Site { fn add_wikitextpage(&mut self, page: WikitextPage) -> Result<(), SiteError> { info!("add wikitext page {}", page.meta().path().display()); - self.pages_that_will_exist.insert(&page); trace!("parsing wikitext page {}", page.meta().path().display()); let mut parser = WikitextParser::new(page.wikitext(), &self.patterns); @@ -99,7 +96,8 @@ impl Site { page.prepare(self)?; let page = Page::new(page.meta().clone(), page); - self.pages.push(page); + self.unprocessed_pages + .insert(page.meta().path(), page.clone()); Ok(()) } @@ -121,13 +119,13 @@ impl Site { } fn process_page(&mut self) -> Result<bool, SiteError> { - if let Some(page) = self.pages.pop() { + if let Some(page) = self.unprocessed_pages.remove_random_page() { debug!( "processing unprocessed page {}", page.meta().path().display() ); let page = page.markdown(self)?; - self.markdown_pages.push(page); + self.markdown_pages.insert(page.meta().path(), page.clone()); Ok(true) } else { trace!("no pages to process"); @@ -135,8 +133,8 @@ impl Site { } } - pub fn markdown_pages(&self) -> &[MarkdownPage] { - &self.markdown_pages + pub fn markdown_pages(&self) -> impl Iterator<Item = &MarkdownPage> { + self.markdown_pages.pages() } pub fn files_only(&self) -> impl Iterator<Item = &Name> { @@ -148,13 +146,11 @@ impl Site { } pub fn is_page(&self, path: &Path) -> bool { - self.pages_that_will_exist.get_path(path).is_some() + self.unprocessed_pages.contains(path) || self.markdown_pages.contains(path) } pub fn page(&self, path: &Path) -> Option<&MarkdownPage> { - self.markdown_pages - .iter() - .find(|&page| page.meta().path() == path) + self.markdown_pages.get_page(path) } fn all_files(&self) -> Result<Vec<Name>, SiteError> { @@ -213,9 +209,9 @@ impl Site { // Is target absolute? if target.starts_with("/") { - if let Some(path) = self.pages_that_will_exist.get_path(target) { + if self.is_page(target) { trace!("absolute target exists"); - return Ok(path.into()); + return Ok(target.into()); } else { trace!("absolute target does not exist"); return Err(SiteError::PageMissing(page.into(), target.into())); @@ -225,9 +221,9 @@ impl Site { // Does a sub-page or file exist? let wanted = page.join(target); trace!("checking for subpage or file {}", wanted.display()); - if let Some(path) = self.pages_that_will_exist.get_path(&wanted) { - trace!("subpage exists: {}", path.display()); - return Ok(path.into()); + if self.is_page(&wanted) { + trace!("subpage exists: {}", wanted.display()); + return Ok(wanted); } else if self.file_exists(&wanted) { trace!("subpage file exists: {}", wanted.display()); return Ok(wanted); @@ -241,9 +237,13 @@ impl Site { parent.display(), path.display() ); - if let Some(path) = self.pages_that_will_exist.get_path(path.as_path()) { - trace!("sibling page exists: {}", path.display()); - return Ok(path.into()); + if let Some(actual) = self.unprocessed_pages.get_path(&path) { + trace!("sibling page exists: {}", actual.display()); + return Ok(actual.into()); + } + if let Some(actual) = self.markdown_pages.get_path(&path) { + trace!("sibling page exists: {}", actual.display()); + return Ok(actual.into()); } // trace!("consider files: {:?}", self.files); if self.file_exists(&path) { @@ -255,9 +255,9 @@ impl Site { // Does target exist relative to root? let wanted = Path::new("/").join(target); trace!("checking for absolute path {}", wanted.display()); - if let Some(path) = self.pages_that_will_exist.get_path(&wanted) { - trace!("page at absolute path exists: {}", path.display()); - return Ok(path.into()); + if self.is_page(&wanted) { + trace!("page at absolute path exists: {}", wanted.display()); + return Ok(wanted); } else if self.file_exists(&wanted) { trace!("file at absolute path exists: {}", wanted.display()); return Ok(wanted); @@ -290,20 +290,42 @@ impl Site { } } -#[derive(Default, Debug)] -struct PageSet { - map: HashMap<String, PathBuf>, +#[derive(Debug)] +struct PageSet<T> { + map: HashMap<String, (PathBuf, T)>, } -impl PageSet { - fn insert(&mut self, page: &WikitextPage) { - let path = page.meta().path(); +impl<T> PageSet<T> { + fn insert(&mut self, path: &Path, page: T) { let key = Self::normalize(path); - self.map.insert(key, path.into()); + self.map.insert(key, (path.into(), page)); + } + + fn contains(&self, path: &Path) -> bool { + self.map.contains_key(&Self::normalize(path)) + } + + fn get_page(&self, path: &Path) -> Option<&T> { + self.map.get(&Self::normalize(path)).map(|(_, page)| page) + } + + fn get_path(&self, wanted: &Path) -> Option<&Path> { + self.map + .get(&Self::normalize(wanted)) + .map(|(path, _)| path.as_path()) } - fn get_path(&self, path: &Path) -> Option<&Path> { - self.map.get(&Self::normalize(path)).map(|x| x.as_ref()) + fn pages(&self) -> impl Iterator<Item = &T> { + self.map.values().map(|(_, page)| page) + } + + fn remove_random_page(&mut self) -> Option<T> { + let mut keys: Vec<String> = self.map.keys().take(1).map(|k| k.into()).collect(); + if let Some(key) = keys.pop() { + self.map.remove(&key).map(|(_, page)| page) + } else { + None + } } fn normalize(path: &Path) -> String { @@ -311,6 +333,14 @@ impl PageSet { } } +impl<T> Default for PageSet<T> { + fn default() -> Self { + Self { + map: HashMap::default(), + } + } +} + #[derive(Debug, Clone, Eq, PartialEq)] pub struct Shortcut { name: String, @@ -371,7 +401,7 @@ mod test { #[test] fn has_no_pages_initially() { - assert_eq!(site().markdown_pages().to_vec(), vec![]); + assert_eq!(site().markdown_pages().count(), 0); } #[test] |