Extract some Tera logic out of site/lib.rs
This commit is contained in:
parent
d9123a8ca4
commit
5fe1036a1d
|
@ -1,6 +1,7 @@
|
||||||
|
pub mod link_checking;
|
||||||
pub mod sass;
|
pub mod sass;
|
||||||
pub mod sitemap;
|
pub mod sitemap;
|
||||||
pub mod link_checking;
|
pub mod tpls;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs::{copy, remove_dir_all};
|
use std::fs::{copy, remove_dir_all};
|
||||||
|
@ -12,6 +13,8 @@ use rayon::prelude::*;
|
||||||
use serde_derive::Serialize;
|
use serde_derive::Serialize;
|
||||||
use tera::{Context, Tera};
|
use tera::{Context, Tera};
|
||||||
|
|
||||||
|
use crate::link_checking::{check_external_links, check_internal_links_with_anchors};
|
||||||
|
use crate::tpls::{load_tera, register_early_global_fns, register_tera_global_fns};
|
||||||
use config::{get_config, Config, Taxonomy as TaxonomyConfig};
|
use config::{get_config, Config, Taxonomy as TaxonomyConfig};
|
||||||
use errors::{bail, Error, Result};
|
use errors::{bail, Error, Result};
|
||||||
use front_matter::InsertAnchor;
|
use front_matter::InsertAnchor;
|
||||||
|
@ -19,11 +22,10 @@ use library::{
|
||||||
find_taxonomies, sort_actual_pages_by_date, Library, Page, Paginator, Section, Taxonomy,
|
find_taxonomies, sort_actual_pages_by_date, Library, Page, Paginator, Section, Taxonomy,
|
||||||
TaxonomyItem,
|
TaxonomyItem,
|
||||||
};
|
};
|
||||||
use templates::{global_fns, render_redirect_template, ZOLA_TERA};
|
use templates::render_redirect_template;
|
||||||
use utils::fs::{copy_directory, create_directory, create_file, ensure_directory_exists};
|
use utils::fs::{copy_directory, create_directory, create_file, ensure_directory_exists};
|
||||||
use utils::net::get_available_port;
|
use utils::net::get_available_port;
|
||||||
use utils::templates::{render_template, rewrite_theme_paths};
|
use utils::templates::render_template;
|
||||||
use crate::link_checking::{check_internal_links_with_anchors, check_external_links};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Site {
|
pub struct Site {
|
||||||
|
@ -74,45 +76,12 @@ impl Site {
|
||||||
let mut config = get_config(config_file);
|
let mut config = get_config(config_file);
|
||||||
config.load_extra_syntaxes(path)?;
|
config.load_extra_syntaxes(path)?;
|
||||||
|
|
||||||
let tpl_glob =
|
|
||||||
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).map_err(|e| Error::chain("Error parsing templates", e))?;
|
|
||||||
if let Some(theme) = config.theme.clone() {
|
if let Some(theme) = config.theme.clone() {
|
||||||
// Grab data from the extra section of the theme
|
// Grab data from the extra section of the theme
|
||||||
config.merge_with_theme(&path.join("themes").join(&theme).join("theme.toml"))?;
|
config.merge_with_theme(&path.join("themes").join(&theme).join("theme.toml"))?;
|
||||||
|
|
||||||
// Test that the templates folder exist for that theme
|
|
||||||
let theme_path = path.join("themes").join(&theme);
|
|
||||||
if !theme_path.join("templates").exists() {
|
|
||||||
bail!("Theme `{}` is missing a templates folder", theme);
|
|
||||||
}
|
|
||||||
|
|
||||||
let theme_tpl_glob = format!(
|
|
||||||
"{}/{}",
|
|
||||||
path.to_string_lossy().replace("\\", "/"),
|
|
||||||
format!("themes/{}/templates/**/*.*ml", theme)
|
|
||||||
);
|
|
||||||
let mut tera_theme = Tera::parse(&theme_tpl_glob)
|
|
||||||
.map_err(|e| Error::chain("Error parsing templates from themes", e))?;
|
|
||||||
rewrite_theme_paths(&mut tera_theme, &theme);
|
|
||||||
// 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)?;
|
|
||||||
}
|
|
||||||
tera.extend(&tera_theme)?;
|
|
||||||
}
|
}
|
||||||
tera.extend(&ZOLA_TERA)?;
|
|
||||||
tera.build_inheritance_chains()?;
|
|
||||||
|
|
||||||
// TODO: Tera doesn't use globset right now so we can load the robots.txt as part
|
let tera = load_tera(path, &config)?;
|
||||||
// of the glob above, therefore we load it manually if it exists.
|
|
||||||
if path.join("templates").join("robots.txt").exists() {
|
|
||||||
tera.add_template_file(path.join("templates").join("robots.txt"), Some("robots.txt"))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let content_path = path.join("content");
|
let content_path = path.join("content");
|
||||||
let static_path = path.join("static");
|
let static_path = path.join("static");
|
||||||
|
@ -145,7 +114,7 @@ impl Site {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The index sections are ALWAYS at those paths
|
/// The index sections are ALWAYS at those paths
|
||||||
/// There are one index section for the basic language + 1 per language
|
/// There are one index section for the default language + 1 per language
|
||||||
fn index_section_paths(&self) -> Vec<(PathBuf, Option<String>)> {
|
fn index_section_paths(&self) -> Vec<(PathBuf, Option<String>)> {
|
||||||
let mut res = vec![(self.content_path.join("_index.md"), None)];
|
let mut res = vec![(self.content_path.join("_index.md"), None)];
|
||||||
for language in &self.config.languages {
|
for language in &self.config.languages {
|
||||||
|
@ -164,11 +133,6 @@ impl Site {
|
||||||
self.live_reload = get_available_port(port_to_avoid);
|
self.live_reload = get_available_port(port_to_avoid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the number of orphan (== without section) pages in the site
|
|
||||||
pub fn get_number_orphan_pages(&self) -> usize {
|
|
||||||
self.library.read().unwrap().get_all_orphan_pages().len()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_base_url(&mut self, base_url: String) {
|
pub fn set_base_url(&mut self, base_url: String) {
|
||||||
let mut imageproc = self.imageproc.lock().expect("Couldn't lock imageproc (set_base_url)");
|
let mut imageproc = self.imageproc.lock().expect("Couldn't lock imageproc (set_base_url)");
|
||||||
imageproc.set_base_url(&base_url);
|
imageproc.set_base_url(&base_url);
|
||||||
|
@ -359,58 +323,14 @@ impl Site {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds global fns that are to be available to shortcodes while
|
// TODO: remove me in favour of the direct call to the fn once rebuild has changed
|
||||||
/// markdown
|
|
||||||
pub fn register_early_global_fns(&mut self) {
|
pub fn register_early_global_fns(&mut self) {
|
||||||
self.tera.register_function(
|
register_early_global_fns(self);
|
||||||
"get_url",
|
|
||||||
global_fns::GetUrl::new(
|
|
||||||
self.config.clone(),
|
|
||||||
self.permalinks.clone(),
|
|
||||||
vec![self.static_path.clone(), self.output_path.clone(), self.content_path.clone()],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
self.tera.register_function(
|
|
||||||
"resize_image",
|
|
||||||
global_fns::ResizeImage::new(self.imageproc.clone()),
|
|
||||||
);
|
|
||||||
self.tera.register_function(
|
|
||||||
"get_image_metadata",
|
|
||||||
global_fns::GetImageMeta::new(self.content_path.clone()),
|
|
||||||
);
|
|
||||||
self.tera.register_function("load_data", global_fns::LoadData::new(self.base_path.clone()));
|
|
||||||
self.tera.register_function("trans", global_fns::Trans::new(self.config.clone()));
|
|
||||||
self.tera.register_function(
|
|
||||||
"get_taxonomy_url",
|
|
||||||
global_fns::GetTaxonomyUrl::new(&self.config.default_language, &self.taxonomies),
|
|
||||||
);
|
|
||||||
self.tera.register_function(
|
|
||||||
"get_file_hash",
|
|
||||||
global_fns::GetFileHash::new(vec![
|
|
||||||
self.static_path.clone(),
|
|
||||||
self.output_path.clone(),
|
|
||||||
self.content_path.clone(),
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove me in favour of the direct call to the fn once rebuild has changed
|
||||||
pub fn register_tera_global_fns(&mut self) {
|
pub fn register_tera_global_fns(&mut self) {
|
||||||
self.tera.register_function(
|
register_tera_global_fns(self);
|
||||||
"get_page",
|
|
||||||
global_fns::GetPage::new(self.base_path.clone(), self.library.clone()),
|
|
||||||
);
|
|
||||||
self.tera.register_function(
|
|
||||||
"get_section",
|
|
||||||
global_fns::GetSection::new(self.base_path.clone(), self.library.clone()),
|
|
||||||
);
|
|
||||||
self.tera.register_function(
|
|
||||||
"get_taxonomy",
|
|
||||||
global_fns::GetTaxonomy::new(
|
|
||||||
&self.config.default_language,
|
|
||||||
self.taxonomies.clone(),
|
|
||||||
self.library.clone(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a page to the site
|
/// Add a page to the site
|
||||||
|
@ -703,6 +623,8 @@ impl Site {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Renders all the aliases for each page/section: a magic HTML template that redirects to
|
||||||
|
/// the canonical one
|
||||||
pub fn render_aliases(&self) -> Result<()> {
|
pub fn render_aliases(&self) -> Result<()> {
|
||||||
ensure_directory_exists(&self.output_path)?;
|
ensure_directory_exists(&self.output_path)?;
|
||||||
let library = self.library.read().unwrap();
|
let library = self.library.read().unwrap();
|
||||||
|
@ -837,6 +759,7 @@ impl Site {
|
||||||
sitemap_url.pop(); // Remove trailing slash
|
sitemap_url.pop(); // Remove trailing slash
|
||||||
sitemap_index.push(sitemap_url);
|
sitemap_index.push(sitemap_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create main sitemap that reference numbered sitemaps
|
// Create main sitemap that reference numbered sitemaps
|
||||||
let mut main_context = Context::new();
|
let mut main_context = Context::new();
|
||||||
main_context.insert("sitemaps", &sitemap_index);
|
main_context.insert("sitemaps", &sitemap_index);
|
||||||
|
@ -993,6 +916,7 @@ impl Site {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove me when reload has changed
|
||||||
/// Used only on reload
|
/// Used only on reload
|
||||||
pub fn render_index(&self) -> Result<()> {
|
pub fn render_index(&self) -> Result<()> {
|
||||||
self.render_section(
|
self.render_section(
|
||||||
|
@ -1061,5 +985,3 @@ impl Site {
|
||||||
.collect::<Result<()>>()
|
.collect::<Result<()>>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Site {}
|
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
|
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
use errors::{Error, ErrorKind, Result};
|
|
||||||
use crate::Site;
|
use crate::Site;
|
||||||
|
use errors::{Error, ErrorKind, Result};
|
||||||
|
|
||||||
/// Very similar to check_external_links but can't be merged as far as I can see since we always
|
/// Very similar to check_external_links but can't be merged as far as I can see since we always
|
||||||
/// want to check the internal links but only the external in zola check :/
|
/// want to check the internal links but only the external in zola check :/
|
||||||
|
@ -152,11 +150,7 @@ pub fn check_external_links(site: &Site) -> Result<()> {
|
||||||
.collect()
|
.collect()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!(
|
println!("> Checked {} external link(s): {} error(s) found.", all_links.len(), errors.len());
|
||||||
"> Checked {} external link(s): {} error(s) found.",
|
|
||||||
all_links.len(),
|
|
||||||
errors.len()
|
|
||||||
);
|
|
||||||
|
|
||||||
if errors.is_empty() {
|
if errors.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
|
@ -18,7 +18,7 @@ pub fn compile_sass(base_path: &Path, output_path: &Path) -> Result<()> {
|
||||||
|
|
||||||
let mut options = Options::default();
|
let mut options = Options::default();
|
||||||
options.output_style = OutputStyle::Compressed;
|
options.output_style = OutputStyle::Compressed;
|
||||||
let mut compiled_paths = compile_sass_glob(&sass_path, output_path, "scss", &options.clone())?;
|
let mut compiled_paths = compile_sass_glob(&sass_path, output_path, "scss", &options)?;
|
||||||
|
|
||||||
options.indented_syntax = true;
|
options.indented_syntax = true;
|
||||||
compiled_paths.extend(compile_sass_glob(&sass_path, output_path, "sass", &options)?);
|
compiled_paths.extend(compile_sass_glob(&sass_path, output_path, "sass", &options)?);
|
||||||
|
|
101
components/site/src/tpls.rs
Normal file
101
components/site/src/tpls.rs
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use tera::Tera;
|
||||||
|
|
||||||
|
use crate::Site;
|
||||||
|
use config::Config;
|
||||||
|
use errors::{bail, Error, Result};
|
||||||
|
use templates::{global_fns, ZOLA_TERA};
|
||||||
|
use utils::templates::rewrite_theme_paths;
|
||||||
|
|
||||||
|
pub fn load_tera(path: &Path, config: &Config) -> Result<Tera> {
|
||||||
|
let tpl_glob =
|
||||||
|
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).map_err(|e| Error::chain("Error parsing templates", e))?;
|
||||||
|
|
||||||
|
if let Some(ref theme) = config.theme {
|
||||||
|
// Test that the templates folder exist for that theme
|
||||||
|
let theme_path = path.join("themes").join(&theme);
|
||||||
|
if !theme_path.join("templates").exists() {
|
||||||
|
bail!("Theme `{}` is missing a templates folder", theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
let theme_tpl_glob = format!(
|
||||||
|
"{}/{}",
|
||||||
|
path.to_string_lossy().replace("\\", "/"),
|
||||||
|
format!("themes/{}/templates/**/*.*ml", theme)
|
||||||
|
);
|
||||||
|
let mut tera_theme = Tera::parse(&theme_tpl_glob)
|
||||||
|
.map_err(|e| Error::chain("Error parsing templates from themes", e))?;
|
||||||
|
rewrite_theme_paths(&mut tera_theme, &theme);
|
||||||
|
|
||||||
|
if theme_path.join("templates").join("robots.txt").exists() {
|
||||||
|
tera_theme.add_template_file(theme_path.join("templates").join("robots.txt"), None)?;
|
||||||
|
}
|
||||||
|
tera.extend(&tera_theme)?;
|
||||||
|
}
|
||||||
|
tera.extend(&ZOLA_TERA)?;
|
||||||
|
tera.build_inheritance_chains()?;
|
||||||
|
|
||||||
|
if path.join("templates").join("robots.txt").exists() {
|
||||||
|
tera.add_template_file(path.join("templates").join("robots.txt"), Some("robots.txt"))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(tera)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds global fns that are to be available to shortcodes while rendering markdown
|
||||||
|
pub fn register_early_global_fns(site: &mut Site) {
|
||||||
|
site.tera.register_function(
|
||||||
|
"get_url",
|
||||||
|
global_fns::GetUrl::new(
|
||||||
|
site.config.clone(),
|
||||||
|
site.permalinks.clone(),
|
||||||
|
vec![site.static_path.clone(), site.output_path.clone(), site.content_path.clone()],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
site.tera
|
||||||
|
.register_function("resize_image", global_fns::ResizeImage::new(site.imageproc.clone()));
|
||||||
|
site.tera.register_function(
|
||||||
|
"get_image_metadata",
|
||||||
|
global_fns::GetImageMeta::new(site.content_path.clone()),
|
||||||
|
);
|
||||||
|
site.tera.register_function("load_data", global_fns::LoadData::new(site.base_path.clone()));
|
||||||
|
site.tera.register_function("trans", global_fns::Trans::new(site.config.clone()));
|
||||||
|
site.tera.register_function(
|
||||||
|
"get_taxonomy_url",
|
||||||
|
global_fns::GetTaxonomyUrl::new(&site.config.default_language, &site.taxonomies),
|
||||||
|
);
|
||||||
|
site.tera.register_function(
|
||||||
|
"get_file_hash",
|
||||||
|
global_fns::GetFileHash::new(vec![
|
||||||
|
site.static_path.clone(),
|
||||||
|
site.output_path.clone(),
|
||||||
|
site.content_path.clone(),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Functions filled once we have parsed all the pages/sections only, so not available in shortcodes
|
||||||
|
pub fn register_tera_global_fns(site: &mut Site) {
|
||||||
|
site.tera.register_function(
|
||||||
|
"get_page",
|
||||||
|
global_fns::GetPage::new(site.base_path.clone(), site.library.clone()),
|
||||||
|
);
|
||||||
|
site.tera.register_function(
|
||||||
|
"get_section",
|
||||||
|
global_fns::GetSection::new(site.base_path.clone(), site.library.clone()),
|
||||||
|
);
|
||||||
|
site.tera.register_function(
|
||||||
|
"get_taxonomy",
|
||||||
|
global_fns::GetTaxonomy::new(
|
||||||
|
&site.config.default_language,
|
||||||
|
site.taxonomies.clone(),
|
||||||
|
site.library.clone(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
|
@ -42,8 +42,8 @@ use ws::{Message, Sender, WebSocket};
|
||||||
|
|
||||||
use errors::{Error as ZolaError, Result};
|
use errors::{Error as ZolaError, Result};
|
||||||
use globset::GlobSet;
|
use globset::GlobSet;
|
||||||
use site::Site;
|
|
||||||
use site::sass::compile_sass;
|
use site::sass::compile_sass;
|
||||||
|
use site::Site;
|
||||||
use utils::fs::copy_file;
|
use utils::fs::copy_file;
|
||||||
|
|
||||||
use crate::console;
|
use crate::console;
|
||||||
|
|
|
@ -54,7 +54,7 @@ pub fn notify_site_size(site: &Site) {
|
||||||
println!(
|
println!(
|
||||||
"-> Creating {} pages ({} orphan), {} sections, and processing {} images",
|
"-> Creating {} pages ({} orphan), {} sections, and processing {} images",
|
||||||
library.pages().len(),
|
library.pages().len(),
|
||||||
site.get_number_orphan_pages(),
|
library.get_all_orphan_pages().len(),
|
||||||
library.sections().len() - 1, // -1 since we do not count the index as a section there
|
library.sections().len() - 1, // -1 since we do not count the index as a section there
|
||||||
site.num_img_ops(),
|
site.num_img_ops(),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue