summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2022-12-04 09:23:27 +0000
committerLars Wirzenius <liw@liw.fi>2022-12-04 09:23:27 +0000
commit35ce15a89637083b4794e7fc2621c477fb073638 (patch)
treee7ef0f4efc06acf77091e7663341fa7a40fca961
parent40ae4ab438a8c2f002c4ed6d1ec9a01fb64c0f4d (diff)
parent875584a3d6a278cf6555f408d509929eb30703da (diff)
downloadriki-35ce15a89637083b4794e7fc2621c477fb073638.tar.gz
Merge branch 'liw/refactor-errors' into 'main'
refactor: create an error type for the html module See merge request larswirzenius/riki!70
-rw-r--r--src/error.rs4
-rw-r--r--src/html.rs50
-rw-r--r--src/page.rs4
-rw-r--r--src/parser.rs8
4 files changed, 50 insertions, 16 deletions
diff --git a/src/error.rs b/src/error.rs
index d58924e..23ef7bc 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,3 +1,4 @@
+use crate::html::HtmlError;
use std::path::PathBuf;
#[derive(Debug, thiserror::Error)]
@@ -94,6 +95,9 @@ pub enum SiteError {
#[error("toc directive arguments 'levels' could not be parsed as an integer: {0}")]
LevelsParse(String, #[source] std::num::ParseIntError),
+
+ #[error(transparent)]
+ HtmlError(#[from] HtmlError),
}
impl SiteError {
diff --git a/src/html.rs b/src/html.rs
index 6d4d009..d023ba4 100644
--- a/src/html.rs
+++ b/src/html.rs
@@ -1,12 +1,10 @@
-use crate::error::SiteError;
-use crate::util::mkdir;
use html_escape::{encode_double_quoted_attribute, encode_text};
use line_col::LineColLookup;
-use log::trace;
+use log::{debug, trace};
use pulldown_cmark::{Event, HeadingLevel, Options, Parser, Tag};
use std::fmt::Write as _;
use std::io::Write;
-use std::path::Path;
+use std::path::{Path, PathBuf};
#[derive(Debug)]
pub struct HtmlPage {
@@ -36,32 +34,34 @@ impl HtmlPage {
&self.body
}
- pub fn serialize(&self) -> Result<String, SiteError> {
+ pub fn serialize(&self) -> Result<String, HtmlError> {
let mut html = Element::new(ElementTag::Html);
html.push_child(Content::Elt(self.head.clone()));
html.push_child(Content::Elt(self.body.clone()));
html.serialize()
}
- pub fn write(&self, filename: &Path) -> Result<(), SiteError> {
+ pub fn write(&self, filename: &Path) -> Result<(), HtmlError> {
if let Some(parent) = filename.parent() {
trace!("parent: {}", parent.display());
if !parent.exists() {
- mkdir(parent)?;
+ debug!("creating directory {}", parent.display());
+ std::fs::create_dir_all(parent)
+ .map_err(|e| HtmlError::CreateDir(parent.into(), e))?;
}
}
trace!("writing HTML: {}", filename.display());
let mut f = std::fs::File::create(filename)
- .map_err(|e| SiteError::CreateFile(filename.into(), e))?;
+ .map_err(|e| HtmlError::CreateFile(filename.into(), e))?;
let html = self.serialize()?;
f.write_all(html.as_bytes())
- .map_err(|e| SiteError::FileWrite(filename.into(), e))?;
+ .map_err(|e| HtmlError::FileWrite(filename.into(), e))?;
Ok(())
}
}
-pub fn parse(markdown: &str) -> Result<Element, SiteError> {
+pub fn parse(markdown: &str) -> Result<Element, HtmlError> {
let mut options = Options::empty();
options.insert(Options::ENABLE_HEADING_ATTRIBUTES);
options.insert(Options::ENABLE_STRIKETHROUGH);
@@ -144,7 +144,7 @@ pub fn parse(markdown: &str) -> Result<Element, SiteError> {
let s = as_plain_text(e.children());
trace!("paragraph text: {:?}", s);
if s.starts_with(": ") || s.contains("\n: ") {
- return Err(SiteError::DefinitionList(loc.line, loc.col));
+ return Err(HtmlError::DefinitionList(loc.line, loc.col));
}
stack.append_child(Content::Elt(e));
}
@@ -258,10 +258,10 @@ impl Element {
}
}
- pub fn serialize(&self) -> Result<String, SiteError> {
+ pub fn serialize(&self) -> Result<String, HtmlError> {
let mut buf = String::new();
self.serialize_to_buf_without_added_newlines(&mut buf)
- .map_err(SiteError::Format)?;
+ .map_err(HtmlError::Format)?;
Ok(buf)
}
@@ -487,3 +487,27 @@ impl Stack {
self.append_child(Content::Elt(e));
}
}
+
+#[derive(Debug, thiserror::Error)]
+pub enum HtmlError {
+ /// Failed to create a directory.
+ #[error("failed to create directory {0}")]
+ CreateDir(PathBuf, #[source] std::io::Error),
+
+ /// Failed to create a file.
+ #[error("failed to create file {0}")]
+ CreateFile(PathBuf, #[source] std::io::Error),
+
+ /// Failed to write to a file.
+ #[error("failed to write to file {0}")]
+ FileWrite(PathBuf, #[source] std::io::Error),
+
+ /// Input contains an attempt to use a definition list in
+ /// Markdown.
+ #[error("attempt to use definition lists in Markdown: line {0}, column {1}")]
+ DefinitionList(usize, usize),
+
+ /// String formatting error. This is likely a programming error.
+ #[error("string formatting error: {0}")]
+ Format(#[source] std::fmt::Error),
+}
diff --git a/src/page.rs b/src/page.rs
index 2e555c8..a8d60a5 100644
--- a/src/page.rs
+++ b/src/page.rs
@@ -151,7 +151,7 @@ impl MarkdownPage {
pub fn body_to_html(&self) -> Result<HtmlPage, SiteError> {
let head = Element::new(ElementTag::Head);
let body = parse(self.markdown())
- .map_err(|e| SiteError::PageProblem(self.meta.path().into(), Box::new(e)))?;
+ .map_err(|e| SiteError::PageProblem(self.meta.path().into(), Box::new(e.into())))?;
Ok(HtmlPage::new(head, body))
}
@@ -163,7 +163,7 @@ impl MarkdownPage {
head.push_child(Content::Elt(title));
let body = parse(self.markdown())
- .map_err(|e| SiteError::PageProblem(self.meta.path().into(), Box::new(e)))?;
+ .map_err(|e| SiteError::PageProblem(self.meta.path().into(), Box::new(e.into())))?;
trace!("MarkdownPage::to_html: head={:?}", head);
Ok(HtmlPage::new(head, body))
diff --git a/src/parser.rs b/src/parser.rs
index c81be74..59ba111 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -198,7 +198,13 @@ impl WikitextParser {
self.drain(6);
break;
}
- _ => return Err(SiteError::wikitext_syntax(line, col, &self.tokens[..std::cmp::min(5, self.tokens.len())])),
+ _ => {
+ return Err(SiteError::wikitext_syntax(
+ line,
+ col,
+ &self.tokens[..std::cmp::min(5, self.tokens.len())],
+ ))
+ }
}
}
if let Some(title) = title {