mirror of
https://github.com/getzola/zola
synced 2024-11-10 06:14:19 +00:00
parent
69fb399726
commit
5caf24f06c
23 changed files with 176 additions and 88 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -342,6 +342,7 @@ dependencies = [
|
|||
"serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntect 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utils 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -616,7 +617,6 @@ dependencies = [
|
|||
name = "errors"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syntect 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tera 0.11.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2229,7 +2229,6 @@ dependencies = [
|
|||
"base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"config 0.1.0",
|
||||
"csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"errors 0.1.0",
|
||||
"imageproc 0.1.0",
|
||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -13,3 +13,4 @@ lazy_static = "1"
|
|||
syntect = "3"
|
||||
|
||||
errors = { path = "../errors" }
|
||||
utils = { path = "../utils" }
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use chrono::Utc;
|
||||
|
@ -9,9 +7,10 @@ use syntect::parsing::{SyntaxSet, SyntaxSetBuilder};
|
|||
use toml;
|
||||
use toml::Value as Toml;
|
||||
|
||||
use errors::{Result, ResultExt};
|
||||
use errors::Result;
|
||||
use highlighting::THEME_SET;
|
||||
use theme::Theme;
|
||||
use utils::fs::read_file_with_error;
|
||||
|
||||
// We want a default base url for tests
|
||||
static DEFAULT_BASE_URL: &'static str = "http://a-website.com";
|
||||
|
@ -66,7 +65,13 @@ impl Taxonomy {
|
|||
|
||||
impl Default for Taxonomy {
|
||||
fn default() -> Taxonomy {
|
||||
Taxonomy { name: String::new(), paginate_by: None, paginate_path: None, rss: false, lang: None }
|
||||
Taxonomy {
|
||||
name: String::new(),
|
||||
paginate_by: None,
|
||||
paginate_path: None,
|
||||
rss: false,
|
||||
lang: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,15 +177,12 @@ impl Config {
|
|||
|
||||
/// Parses a config file from the given path
|
||||
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Config> {
|
||||
let mut content = String::new();
|
||||
let path = path.as_ref();
|
||||
let file_name = path.file_name().unwrap();
|
||||
File::open(path)
|
||||
.chain_err(|| {
|
||||
format!("No `{:?}` file found. Are you in the right directory?", file_name)
|
||||
})?
|
||||
.read_to_string(&mut content)?;
|
||||
|
||||
let content = read_file_with_error(
|
||||
path,
|
||||
&format!("No `{:?}` file found. Are you in the right directory?", file_name),
|
||||
)?;
|
||||
Config::parse(&content)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate toml;
|
||||
#[macro_use]
|
||||
extern crate errors;
|
||||
extern crate chrono;
|
||||
extern crate globset;
|
||||
extern crate toml;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate syntect;
|
||||
|
||||
#[macro_use]
|
||||
extern crate errors;
|
||||
extern crate utils;
|
||||
|
||||
mod config;
|
||||
pub mod highlighting;
|
||||
mod theme;
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use toml::Value as Toml;
|
||||
|
||||
use errors::{Result, ResultExt};
|
||||
use errors::Result;
|
||||
use utils::fs::read_file_with_error;
|
||||
|
||||
/// Holds the data from a `theme.toml` file.
|
||||
/// There are other fields than `extra` in it but Zola
|
||||
|
@ -40,15 +39,12 @@ impl Theme {
|
|||
|
||||
/// Parses a theme file from the given path
|
||||
pub fn from_file(path: &PathBuf) -> Result<Theme> {
|
||||
let mut content = String::new();
|
||||
File::open(path)
|
||||
.chain_err(|| {
|
||||
let content = read_file_with_error(
|
||||
path,
|
||||
"No `theme.toml` file found. \
|
||||
Is the `theme` defined in your `config.toml present in the `themes` directory \
|
||||
and does it have a `theme.toml` inside?"
|
||||
})?
|
||||
.read_to_string(&mut content)?;
|
||||
|
||||
and does it have a `theme.toml` inside?",
|
||||
)?;
|
||||
Theme::parse(&content)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ version = "0.1.0"
|
|||
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
error-chain = "0.12"
|
||||
tera = "0.11"
|
||||
toml = "0.4"
|
||||
image = "0.20"
|
||||
|
|
|
@ -1,27 +1,102 @@
|
|||
#![allow(unused_doc_comments)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate error_chain;
|
||||
extern crate image;
|
||||
extern crate syntect;
|
||||
extern crate tera;
|
||||
extern crate toml;
|
||||
|
||||
error_chain! {
|
||||
errors {}
|
||||
use std::convert::Into;
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt;
|
||||
|
||||
links {
|
||||
Tera(tera::Error, tera::ErrorKind);
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub enum ErrorKind {
|
||||
Msg(String),
|
||||
Tera(tera::Error),
|
||||
Io(::std::io::Error),
|
||||
Toml(toml::de::Error),
|
||||
Image(image::ImageError),
|
||||
Syntect(syntect::LoadingError),
|
||||
}
|
||||
|
||||
foreign_links {
|
||||
Io(::std::io::Error);
|
||||
Toml(toml::de::Error);
|
||||
Image(image::ImageError);
|
||||
Syntect(syntect::LoadingError);
|
||||
/// The Error type
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
/// Kind of error
|
||||
pub kind: ErrorKind,
|
||||
pub source: Option<Box<dyn StdError>>,
|
||||
}
|
||||
unsafe impl Sync for Error {}
|
||||
unsafe impl Send for Error {}
|
||||
|
||||
impl StdError for Error {
|
||||
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
||||
self.source.as_ref().map(|c| &**c)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.kind {
|
||||
ErrorKind::Msg(ref message) => write!(f, "{}", message),
|
||||
ErrorKind::Tera(ref e) => write!(f, "{}", e),
|
||||
ErrorKind::Io(ref e) => write!(f, "{}", e),
|
||||
ErrorKind::Toml(ref e) => write!(f, "{}", e),
|
||||
ErrorKind::Image(ref e) => write!(f, "{}", e),
|
||||
ErrorKind::Syntect(ref e) => write!(f, "{}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// Creates generic error
|
||||
pub fn msg(value: impl ToString) -> Self {
|
||||
Self { kind: ErrorKind::Msg(value.to_string()), source: None }
|
||||
}
|
||||
|
||||
/// Creates generic error with a cause
|
||||
pub fn chain(value: impl ToString, source: impl Into<Box<dyn StdError>>) -> Self {
|
||||
Self { kind: ErrorKind::Msg(value.to_string()), source: Some(source.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl From<&str> for Error {
|
||||
fn from(e: &str) -> Self {
|
||||
Self::msg(e)
|
||||
}
|
||||
}
|
||||
impl From<String> for Error {
|
||||
fn from(e: String) -> Self {
|
||||
Self::msg(e)
|
||||
}
|
||||
}
|
||||
impl From<toml::de::Error> for Error {
|
||||
fn from(e: toml::de::Error) -> Self {
|
||||
Self { kind: ErrorKind::Toml(e), source: None }
|
||||
}
|
||||
}
|
||||
impl From<syntect::LoadingError> for Error {
|
||||
fn from(e: syntect::LoadingError) -> Self {
|
||||
Self { kind: ErrorKind::Syntect(e), source: None }
|
||||
}
|
||||
}
|
||||
impl From<tera::Error> for Error {
|
||||
fn from(e: tera::Error) -> Self {
|
||||
Self { kind: ErrorKind::Tera(e), source: None }
|
||||
}
|
||||
}
|
||||
impl From<::std::io::Error> for Error {
|
||||
fn from(e: ::std::io::Error) -> Self {
|
||||
Self { kind: ErrorKind::Io(e), source: None }
|
||||
}
|
||||
}
|
||||
impl From<image::ImageError> for Error {
|
||||
fn from(e: image::ImageError) -> Self {
|
||||
Self { kind: ErrorKind::Image(e), source: None }
|
||||
}
|
||||
}
|
||||
/// Convenient wrapper around std::Result.
|
||||
pub type Result<T> = ::std::result::Result<T, Error>;
|
||||
|
||||
// So we can use bail! in all other crates
|
||||
#[macro_export]
|
||||
macro_rules! bail {
|
||||
|
|
|
@ -12,7 +12,7 @@ extern crate toml;
|
|||
extern crate errors;
|
||||
extern crate utils;
|
||||
|
||||
use errors::{Result, ResultExt};
|
||||
use errors::{Result, Error};
|
||||
use regex::Regex;
|
||||
use std::path::Path;
|
||||
|
||||
|
@ -71,8 +71,8 @@ pub fn split_section_content(
|
|||
content: &str,
|
||||
) -> Result<(SectionFrontMatter, String)> {
|
||||
let (front_matter, content) = split_content(file_path, content)?;
|
||||
let meta = SectionFrontMatter::parse(&front_matter).chain_err(|| {
|
||||
format!("Error when parsing front matter of section `{}`", file_path.to_string_lossy())
|
||||
let meta = SectionFrontMatter::parse(&front_matter).map_err(|e| {
|
||||
Error::chain(format!("Error when parsing front matter of section `{}`", file_path.to_string_lossy()), e)
|
||||
})?;
|
||||
Ok((meta, content))
|
||||
}
|
||||
|
@ -81,8 +81,8 @@ pub fn split_section_content(
|
|||
/// Returns a parsed `PageFrontMatter` and the rest of the content
|
||||
pub fn split_page_content(file_path: &Path, content: &str) -> Result<(PageFrontMatter, String)> {
|
||||
let (front_matter, content) = split_content(file_path, content)?;
|
||||
let meta = PageFrontMatter::parse(&front_matter).chain_err(|| {
|
||||
format!("Error when parsing front matter of page `{}`", file_path.to_string_lossy())
|
||||
let meta = PageFrontMatter::parse(&front_matter).map_err(|e| {
|
||||
Error::chain(format!("Error when parsing front matter of page `{}`", file_path.to_string_lossy()), e)
|
||||
})?;
|
||||
Ok((meta, content))
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ use image::{FilterType, GenericImageView};
|
|||
use rayon::prelude::*;
|
||||
use regex::Regex;
|
||||
|
||||
use errors::{Result, ResultExt};
|
||||
use errors::{Result, Error};
|
||||
use utils::fs as ufs;
|
||||
|
||||
static RESIZED_SUBDIR: &'static str = "processed_images";
|
||||
|
@ -456,7 +456,7 @@ impl Processor {
|
|||
let target =
|
||||
self.resized_path.join(Self::op_filename(*hash, op.collision_id, op.format));
|
||||
op.perform(&self.content_path, &target)
|
||||
.chain_err(|| format!("Failed to process image: {}", op.source))
|
||||
.map_err(|e| Error::chain(format!("Failed to process image: {}", op.source), e))
|
||||
})
|
||||
.collect::<Result<()>>()
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use slug::slugify;
|
|||
use tera::{Context as TeraContext, Tera};
|
||||
|
||||
use config::Config;
|
||||
use errors::{Result, ResultExt};
|
||||
use errors::{Result, Error};
|
||||
use front_matter::{split_page_content, InsertAnchor, PageFrontMatter};
|
||||
use library::Library;
|
||||
use rendering::{render_content, Header, RenderContext};
|
||||
|
@ -234,7 +234,7 @@ impl Page {
|
|||
context.tera_context.insert("page", &SerializingPage::from_page_basic(self, None));
|
||||
|
||||
let res = render_content(&self.raw_content, &context)
|
||||
.chain_err(|| format!("Failed to render content of {}", self.file.path.display()))?;
|
||||
.map_err(|e| Error::chain(format!("Failed to render content of {}", self.file.path.display()), e))?;
|
||||
|
||||
self.summary = res.summary_len.map(|l| res.body[0..l].to_owned());
|
||||
self.content = res.body;
|
||||
|
@ -258,7 +258,7 @@ impl Page {
|
|||
context.insert("lang", &self.lang);
|
||||
|
||||
render_template(&tpl_name, tera, &context, &config.theme)
|
||||
.chain_err(|| format!("Failed to render page '{}'", self.file.path.display()))
|
||||
.map_err(|e| Error::chain(format!("Failed to render page '{}'", self.file.path.display()), e))
|
||||
}
|
||||
|
||||
/// Creates a vectors of asset URLs.
|
||||
|
|
|
@ -5,7 +5,7 @@ use slotmap::Key;
|
|||
use tera::{Context as TeraContext, Tera};
|
||||
|
||||
use config::Config;
|
||||
use errors::{Result, ResultExt};
|
||||
use errors::{Result, Error};
|
||||
use front_matter::{split_section_content, SectionFrontMatter};
|
||||
use rendering::{render_content, Header, RenderContext};
|
||||
use utils::fs::{find_related_assets, read_file};
|
||||
|
@ -172,7 +172,7 @@ impl Section {
|
|||
context.tera_context.insert("section", &SerializingSection::from_section_basic(self, None));
|
||||
|
||||
let res = render_content(&self.raw_content, &context)
|
||||
.chain_err(|| format!("Failed to render content of {}", self.file.path.display()))?;
|
||||
.map_err(|e| Error::chain(format!("Failed to render content of {}", self.file.path.display()), e))?;
|
||||
self.content = res.body;
|
||||
self.toc = res.toc;
|
||||
Ok(())
|
||||
|
@ -190,7 +190,7 @@ impl Section {
|
|||
context.insert("lang", &self.lang);
|
||||
|
||||
render_template(tpl_name, tera, &context, &config.theme)
|
||||
.chain_err(|| format!("Failed to render section '{}'", self.file.path.display()))
|
||||
.map_err(|e| Error::chain(format!("Failed to render section '{}'", self.file.path.display()), e))
|
||||
}
|
||||
|
||||
/// Is this the index section?
|
||||
|
|
|
@ -4,7 +4,7 @@ use slotmap::Key;
|
|||
use tera::{to_value, Context, Tera, Value};
|
||||
|
||||
use config::Config;
|
||||
use errors::{Result, ResultExt};
|
||||
use errors::{Result, Error};
|
||||
use utils::templates::render_template;
|
||||
|
||||
use content::{Section, SerializingPage, SerializingSection};
|
||||
|
@ -222,7 +222,7 @@ impl<'a> Paginator<'a> {
|
|||
context.insert("paginator", &self.build_paginator_context(pager));
|
||||
|
||||
render_template(&self.template, tera, &context, &config.theme)
|
||||
.chain_err(|| format!("Failed to render pager {}", pager.index))
|
||||
.map_err(|e| Error::chain(format!("Failed to render pager {}", pager.index), e))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ use slug::slugify;
|
|||
use tera::{Context, Tera};
|
||||
|
||||
use config::{Config, Taxonomy as TaxonomyConfig};
|
||||
use errors::{Result, ResultExt};
|
||||
use errors::{Result, Error};
|
||||
use utils::templates::render_template;
|
||||
|
||||
use content::SerializingPage;
|
||||
|
@ -145,7 +145,7 @@ impl Taxonomy {
|
|||
context.insert("current_path", &format!("/{}/{}", self.kind.name, item.slug));
|
||||
|
||||
render_template(&format!("{}/single.html", self.kind.name), tera, &context, &config.theme)
|
||||
.chain_err(|| format!("Failed to render single term {} page.", self.kind.name))
|
||||
.map_err(|e| Error::chain(format!("Failed to render single term {} page.", self.kind.name), e))
|
||||
}
|
||||
|
||||
pub fn render_all_terms(
|
||||
|
@ -164,7 +164,7 @@ impl Taxonomy {
|
|||
context.insert("current_path", &self.kind.name);
|
||||
|
||||
render_template(&format!("{}/list.html", self.kind.name), tera, &context, &config.theme)
|
||||
.chain_err(|| format!("Failed to render a list of {} page.", self.kind.name))
|
||||
.map_err(|e| Error::chain(format!("Failed to render a list of {} page.", self.kind.name), e))
|
||||
}
|
||||
|
||||
pub fn to_serialized<'a>(&'a self, library: &'a Library) -> SerializedTaxonomy<'a> {
|
||||
|
@ -334,7 +334,7 @@ mod tests {
|
|||
let err = taxonomies.unwrap_err();
|
||||
// no path as this is created by Default
|
||||
assert_eq!(
|
||||
err.description(),
|
||||
format!("{}", err),
|
||||
"Page `` has taxonomy `tags` which is not defined in config.toml"
|
||||
);
|
||||
}
|
||||
|
@ -442,7 +442,7 @@ mod tests {
|
|||
let err = taxonomies.unwrap_err();
|
||||
// no path as this is created by Default
|
||||
assert_eq!(
|
||||
err.description(),
|
||||
format!("{}", err),
|
||||
"Page `` has taxonomy `tags` which is not available in that language"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use regex::Regex;
|
|||
use tera::{to_value, Context, Map, Value};
|
||||
|
||||
use context::RenderContext;
|
||||
use errors::{Result, ResultExt};
|
||||
use errors::{Result, Error};
|
||||
|
||||
// This include forces recompiling this source file if the grammar file changes.
|
||||
// Uncomment it when doing changes to the .pest file
|
||||
|
@ -116,7 +116,7 @@ fn render_shortcode(
|
|||
let res = context
|
||||
.tera
|
||||
.render(&tpl_name, &tera_context)
|
||||
.chain_err(|| format!("Failed to render {} shortcode", name))?;
|
||||
.map_err(|e| Error::chain(format!("Failed to render {} shortcode", name), e))?;
|
||||
|
||||
// Small hack to avoid having multiple blank lines because of Tera tags for example
|
||||
// A blank like will cause the markdown parser to think we're out of HTML and start looking
|
||||
|
|
|
@ -660,7 +660,7 @@ fn can_show_error_message_for_invalid_external_links() {
|
|||
let res = render_content("[a link](http://google.comy)", &context);
|
||||
assert!(res.is_err());
|
||||
let err = res.unwrap_err();
|
||||
assert!(err.description().contains("Link http://google.comy is not valid"));
|
||||
assert!(format!("{}", err).contains("Link http://google.comy is not valid"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -30,7 +30,7 @@ use sass_rs::{compile_file, Options as SassOptions, OutputStyle};
|
|||
use tera::{Context, Tera};
|
||||
|
||||
use config::{get_config, Config};
|
||||
use errors::{Result, ResultExt};
|
||||
use errors::{Result, Error};
|
||||
use front_matter::InsertAnchor;
|
||||
use library::{
|
||||
find_taxonomies, sort_actual_pages_by_date, Library, Page, Paginator, Section, Taxonomy,
|
||||
|
@ -87,7 +87,7 @@ impl Site {
|
|||
format!("{}/{}", path.to_string_lossy().replace("\\", "/"), "templates/**/*.*ml");
|
||||
// Only parsing as we might be extending templates from themes and that would error
|
||||
// as we haven't loaded them yet
|
||||
let mut tera = Tera::parse(&tpl_glob).chain_err(|| "Error parsing templates")?;
|
||||
let mut tera = Tera::parse(&tpl_glob).map_err(|e| Error::chain("Error parsing templates", e))?;
|
||||
if let Some(theme) = config.theme.clone() {
|
||||
// Grab data from the extra section of the theme
|
||||
config.merge_with_theme(&path.join("themes").join(&theme).join("theme.toml"))?;
|
||||
|
@ -104,9 +104,9 @@ impl Site {
|
|||
format!("themes/{}/templates/**/*.*ml", theme)
|
||||
);
|
||||
let mut tera_theme =
|
||||
Tera::parse(&theme_tpl_glob).chain_err(|| "Error parsing templates from themes")?;
|
||||
Tera::parse(&theme_tpl_glob).map_err(|e| Error::chain("Error parsing templates from themes", e))?;
|
||||
rewrite_theme_paths(&mut tera_theme, &theme);
|
||||
// TODO: same as below
|
||||
// TODO: we do that twice, make it dry?
|
||||
if theme_path.join("templates").join("robots.txt").exists() {
|
||||
tera_theme
|
||||
.add_template_file(theme_path.join("templates").join("robots.txt"), None)?;
|
||||
|
@ -470,7 +470,7 @@ impl Site {
|
|||
pub fn clean(&self) -> Result<()> {
|
||||
if self.output_path.exists() {
|
||||
// Delete current `public` directory so we can start fresh
|
||||
remove_dir_all(&self.output_path).chain_err(|| "Couldn't delete output directory")?;
|
||||
remove_dir_all(&self.output_path).map_err(|e| Error::chain("Couldn't delete output directory", e))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -11,7 +11,6 @@ pulldown-cmark = "0.2"
|
|||
toml = "0.4"
|
||||
csv = "1"
|
||||
serde_json = "1.0"
|
||||
error-chain = "0.12"
|
||||
reqwest = "0.9"
|
||||
url = "1.5"
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
extern crate error_chain;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ pub mod global_fns;
|
|||
|
||||
use tera::{Context, Tera};
|
||||
|
||||
use errors::{Result, ResultExt};
|
||||
use errors::{Result, Error};
|
||||
|
||||
lazy_static! {
|
||||
pub static ref ZOLA_TERA: Tera = {
|
||||
|
@ -57,5 +57,5 @@ pub fn render_redirect_template(url: &str, tera: &Tera) -> Result<String> {
|
|||
context.insert("url", &url);
|
||||
|
||||
tera.render("internal/alias.html", &context)
|
||||
.chain_err(|| format!("Failed to render alias for '{}'", url))
|
||||
.map_err(|e| Error::chain(format!("Failed to render alias for '{}'", url), e))
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::path::{Path, PathBuf};
|
|||
use std::time::SystemTime;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use errors::{Result, ResultExt};
|
||||
use errors::{Result, Error};
|
||||
|
||||
pub fn is_path_in_directory(parent: &Path, path: &Path) -> Result<bool> {
|
||||
let canonical_path = path
|
||||
|
@ -19,7 +19,8 @@ pub fn is_path_in_directory(parent: &Path, path: &Path) -> Result<bool> {
|
|||
|
||||
/// Create a file with the content given
|
||||
pub fn create_file(path: &Path, content: &str) -> Result<()> {
|
||||
let mut file = File::create(&path).chain_err(|| format!("Failed to create {:?}", path))?;
|
||||
let mut file = File::create(&path)
|
||||
.map_err(|e| Error::chain(format!("Failed to create {:?}", path), e))?;
|
||||
file.write_all(content.as_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -37,7 +38,7 @@ pub fn ensure_directory_exists(path: &Path) -> Result<()> {
|
|||
pub fn create_directory(path: &Path) -> Result<()> {
|
||||
if !path.exists() {
|
||||
create_dir_all(path)
|
||||
.chain_err(|| format!("Was not able to create folder {}", path.display()))?;
|
||||
.map_err(|e| Error::chain(format!("Was not able to create folder {}", path.display()), e))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -46,7 +47,7 @@ pub fn create_directory(path: &Path) -> Result<()> {
|
|||
pub fn read_file(path: &Path) -> Result<String> {
|
||||
let mut content = String::new();
|
||||
File::open(path)
|
||||
.chain_err(|| format!("Failed to open '{:?}'", path.display()))?
|
||||
.map_err(|e| Error::chain(format!("Failed to open '{:?}'", path.display()), e))?
|
||||
.read_to_string(&mut content)?;
|
||||
|
||||
// Remove utf-8 BOM if any.
|
||||
|
@ -57,6 +58,19 @@ pub fn read_file(path: &Path) -> Result<String> {
|
|||
Ok(content)
|
||||
}
|
||||
|
||||
/// Return the content of a file, with error handling added.
|
||||
/// The default error message is overwritten by the message given.
|
||||
/// That means it is allocation 2 strings, oh well
|
||||
pub fn read_file_with_error(path: &Path, message: &str) -> Result<String> {
|
||||
let res = read_file(&path);
|
||||
if res.is_ok() {
|
||||
return res;
|
||||
}
|
||||
let mut err = Error::msg(message);
|
||||
err.source = res.unwrap_err().source;
|
||||
Err(err)
|
||||
}
|
||||
|
||||
/// Looks into the current folder for the path and see if there's anything that is not a .md
|
||||
/// file. Those will be copied next to the rendered .html file
|
||||
pub fn find_related_assets(path: &Path) -> Vec<PathBuf> {
|
||||
|
|
1
docs/templates/page.html
vendored
1
docs/templates/page.html
vendored
|
@ -4,4 +4,5 @@
|
|||
{% block doc_content %}
|
||||
<h1>{{page.title}}</h1>
|
||||
{{page.content | safe}}
|
||||
{{hey}}
|
||||
{% endblock doc_content %}
|
||||
|
|
|
@ -36,7 +36,7 @@ use ctrlc;
|
|||
use notify::{watcher, RecursiveMode, Watcher};
|
||||
use ws::{Message, Sender, WebSocket};
|
||||
|
||||
use errors::{Result, ResultExt};
|
||||
use errors::{Result, Error as ZolaError};
|
||||
use site::Site;
|
||||
use utils::fs::copy_file;
|
||||
|
||||
|
@ -179,23 +179,23 @@ pub fn serve(
|
|||
let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
|
||||
watcher
|
||||
.watch("content/", RecursiveMode::Recursive)
|
||||
.chain_err(|| "Can't watch the `content` folder. Does it exist?")?;
|
||||
.map_err(|e| ZolaError::chain("Can't watch the `content` folder. Does it exist?", e))?;
|
||||
watcher
|
||||
.watch(config_file, RecursiveMode::Recursive)
|
||||
.chain_err(|| "Can't watch the `config` file. Does it exist?")?;
|
||||
.map_err(|e| ZolaError::chain("Can't watch the `config` file. Does it exist?", e))?;
|
||||
|
||||
if Path::new("static").exists() {
|
||||
watching_static = true;
|
||||
watcher
|
||||
.watch("static/", RecursiveMode::Recursive)
|
||||
.chain_err(|| "Can't watch the `static` folder.")?;
|
||||
.map_err(|e| ZolaError::chain("Can't watch the `static` folder.", e))?;
|
||||
}
|
||||
|
||||
if Path::new("templates").exists() {
|
||||
watching_templates = true;
|
||||
watcher
|
||||
.watch("templates/", RecursiveMode::Recursive)
|
||||
.chain_err(|| "Can't watch the `templates` folder.")?;
|
||||
.map_err(|e| ZolaError::chain("Can't watch the `templates` folder.", e))?;
|
||||
}
|
||||
|
||||
// Sass support is optional so don't make it an error to no have a sass folder
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::env;
|
||||
use std::error::Error as StdError;
|
||||
use std::io::Write;
|
||||
use std::time::Instant;
|
||||
|
||||
|
@ -6,7 +7,6 @@ use atty;
|
|||
use chrono::Duration;
|
||||
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
|
||||
|
||||
use errors::Error;
|
||||
use site::Site;
|
||||
|
||||
lazy_static! {
|
||||
|
@ -91,13 +91,15 @@ pub fn report_elapsed_time(instant: Instant) {
|
|||
}
|
||||
|
||||
/// Display an error message and the actual error(s)
|
||||
pub fn unravel_errors(message: &str, error: &Error) {
|
||||
pub fn unravel_errors(message: &str, error: &StdError) {
|
||||
if !message.is_empty() {
|
||||
self::error(message);
|
||||
}
|
||||
self::error(&format!("Error: {}", error));
|
||||
for e in error.iter().skip(1) {
|
||||
let mut cause = error.source();
|
||||
while let Some(e) = cause {
|
||||
self::error(&format!("Reason: {}", e));
|
||||
cause = e.source();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue