use std::path::PathBuf;
use thiserror::Error;
use crate::markdown::BrokenWikiLink;
#[derive(Debug, Error)]
pub enum Error {
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("config parse error: {0}")]
Config(#[from] toml::de::Error),
#[error("missing YAML frontmatter")]
MissingFrontmatter,
#[error("frontmatter parse error: {0}")]
FrontmatterParse(#[from] serde_yml::Error),
#[error("failed to load {path}")]
LoadPage {
path: PathBuf,
#[source]
source: Box<Error>,
},
#[error("slug collision: '{slug}' claimed by {path1} and {path2}")]
SlugCollision {
slug: String,
path1: PathBuf,
path2: PathBuf,
},
#[error("failed to load theme from {path}")]
ThemeLoad {
path: PathBuf,
#[source]
source: Box<Error>,
},
#[error("theme is missing required templates: {}", missing.join(", "))]
ThemeMissingTemplates { missing: Vec<String> },
#[error("template render error: {0}")]
Tera(#[from] tera::Error),
#[error("broken wiki-links found:\n{}", format_broken_links(.0))]
BrokenWikiLinks(Vec<BrokenWikiLink>),
#[error("file watcher error: {0}")]
Notify(#[from] notify::Error),
#[error("refusing unsafe path '{}': {reason}", path.display())]
UnsafeOutputPath { path: PathBuf, reason: &'static str },
#[error("{} is not valid UTF-8", path.display())]
NotUtf8 { path: PathBuf },
#[error("invalid config: {field}: {message}")]
InvalidConfig {
field: &'static str,
message: String,
},
#[error("scaffold error: {message}")]
Scaffold { message: String },
#[error("failed to generate favicon from '{}': {reason}", path.display())]
Favicon { path: PathBuf, reason: String },
}
fn format_broken_links(links: &[BrokenWikiLink]) -> String {
links
.iter()
.map(|link| {
format!(
" - page \"{}\" references missing wiki-link: \"{}\"",
link.source, link.target
)
})
.collect::<Vec<_>>()
.join("\n")
}