mirror of
https://github.com/getzola/zola
synced 2024-11-10 14:24:27 +00:00
First draft of theme support
This commit is contained in:
parent
ce371f2ed5
commit
c77cc9b170
20 changed files with 115 additions and 31 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -4,6 +4,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"errors 0.1.0",
|
"errors 0.1.0",
|
||||||
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"tera 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -775,6 +776,7 @@ dependencies = [
|
||||||
"serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tera 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tera 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"utils 0.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1163,6 +1165,7 @@ dependencies = [
|
||||||
"serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"slug 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"slug 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tera 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tera 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"utils 0.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -23,6 +23,8 @@ pub struct Config {
|
||||||
/// Base URL of the site, the only required config argument
|
/// Base URL of the site, the only required config argument
|
||||||
pub base_url: String,
|
pub base_url: String,
|
||||||
|
|
||||||
|
/// Theme to use
|
||||||
|
pub theme: Option<String>,
|
||||||
/// Title of the site. Defaults to None
|
/// Title of the site. Defaults to None
|
||||||
pub title: Option<String>,
|
pub title: Option<String>,
|
||||||
/// Whether to highlight all code blocks found in markdown files. Defaults to false
|
/// Whether to highlight all code blocks found in markdown files. Defaults to false
|
||||||
|
@ -130,6 +132,7 @@ impl Default for Config {
|
||||||
fn default() -> Config {
|
fn default() -> Config {
|
||||||
Config {
|
Config {
|
||||||
title: Some("".to_string()),
|
title: Some("".to_string()),
|
||||||
|
theme: None,
|
||||||
base_url: "http://a-website.com/".to_string(),
|
base_url: "http://a-website.com/".to_string(),
|
||||||
highlight_code: Some(true),
|
highlight_code: Some(true),
|
||||||
highlight_theme: Some("base16-ocean-dark".to_string()),
|
highlight_theme: Some("base16-ocean-dark".to_string()),
|
||||||
|
|
|
@ -12,6 +12,7 @@ use errors::{Result, ResultExt};
|
||||||
use config::Config;
|
use config::Config;
|
||||||
use utils::fs::{read_file, find_related_assets};
|
use utils::fs::{read_file, find_related_assets};
|
||||||
use utils::site::get_reading_analytics;
|
use utils::site::get_reading_analytics;
|
||||||
|
use utils::templates::render_template;
|
||||||
use front_matter::{PageFrontMatter, InsertAnchor, split_page_content};
|
use front_matter::{PageFrontMatter, InsertAnchor, split_page_content};
|
||||||
use rendering::{Context, Header, markdown_to_html};
|
use rendering::{Context, Header, markdown_to_html};
|
||||||
|
|
||||||
|
@ -154,7 +155,7 @@ impl Page {
|
||||||
context.add("current_url", &self.permalink);
|
context.add("current_url", &self.permalink);
|
||||||
context.add("current_path", &self.path);
|
context.add("current_path", &self.path);
|
||||||
|
|
||||||
tera.render(&tpl_name, &context)
|
render_template(&tpl_name, tera, &context, config.theme.clone())
|
||||||
.chain_err(|| format!("Failed to render page '{}'", self.file.path.display()))
|
.chain_err(|| format!("Failed to render page '{}'", self.file.path.display()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ use config::Config;
|
||||||
use front_matter::{SectionFrontMatter, split_section_content};
|
use front_matter::{SectionFrontMatter, split_section_content};
|
||||||
use errors::{Result, ResultExt};
|
use errors::{Result, ResultExt};
|
||||||
use utils::fs::read_file;
|
use utils::fs::read_file;
|
||||||
|
use utils::templates::render_template;
|
||||||
use rendering::{Context, Header, markdown_to_html};
|
use rendering::{Context, Header, markdown_to_html};
|
||||||
|
|
||||||
use page::Page;
|
use page::Page;
|
||||||
|
@ -113,7 +114,7 @@ impl Section {
|
||||||
context.add("current_url", &self.permalink);
|
context.add("current_url", &self.permalink);
|
||||||
context.add("current_path", &self.path);
|
context.add("current_path", &self.path);
|
||||||
|
|
||||||
tera.render(&tpl_name, &context)
|
render_template(&tpl_name, tera, &context, config.theme.clone())
|
||||||
.chain_err(|| format!("Failed to render section '{}'", self.file.path.display()))
|
.chain_err(|| format!("Failed to render section '{}'", self.file.path.display()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ serde_derive = "1.0"
|
||||||
errors = { path = "../errors" }
|
errors = { path = "../errors" }
|
||||||
config = { path = "../config" }
|
config = { path = "../config" }
|
||||||
content = { path = "../content" }
|
content = { path = "../content" }
|
||||||
|
utils = { path = "../utils" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
front_matter = { path = "../front_matter" }
|
front_matter = { path = "../front_matter" }
|
||||||
|
|
|
@ -5,6 +5,7 @@ extern crate tera;
|
||||||
extern crate errors;
|
extern crate errors;
|
||||||
extern crate config;
|
extern crate config;
|
||||||
extern crate content;
|
extern crate content;
|
||||||
|
extern crate utils;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate front_matter;
|
extern crate front_matter;
|
||||||
|
@ -16,6 +17,7 @@ use tera::{Tera, Context, to_value, Value};
|
||||||
use errors::{Result, ResultExt};
|
use errors::{Result, ResultExt};
|
||||||
use config::Config;
|
use config::Config;
|
||||||
use content::{Page, Section};
|
use content::{Page, Section};
|
||||||
|
use utils::templates::render_template;
|
||||||
|
|
||||||
|
|
||||||
/// A list of all the pages in the paginator with their index and links
|
/// A list of all the pages in the paginator with their index and links
|
||||||
|
@ -170,7 +172,7 @@ impl<'a> Paginator<'a> {
|
||||||
context.add("current_path", &pager.path);
|
context.add("current_path", &pager.path);
|
||||||
context.add("paginator", &self.build_paginator_context(pager));
|
context.add("paginator", &self.build_paginator_context(pager));
|
||||||
|
|
||||||
tera.render(&self.section.get_template_name(), &context)
|
render_template(&self.section.get_template_name(), tera, &context, config.theme.clone())
|
||||||
.chain_err(|| format!("Failed to render pager {} of section '{}'", pager.index, self.section.file.path.display()))
|
.chain_err(|| format!("Failed to render pager {} of section '{}'", pager.index, self.section.file.path.display()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ use sass_rs::{Options, compile_file};
|
||||||
use errors::{Result, ResultExt};
|
use errors::{Result, ResultExt};
|
||||||
use config::{Config, get_config};
|
use config::{Config, get_config};
|
||||||
use utils::fs::{create_file, create_directory, ensure_directory_exists};
|
use utils::fs::{create_file, create_directory, ensure_directory_exists};
|
||||||
|
use utils::templates::render_template;
|
||||||
use content::{Page, Section, populate_previous_and_next_pages, sort_pages};
|
use content::{Page, Section, populate_previous_and_next_pages, sort_pages};
|
||||||
use templates::{GUTENBERG_TERA, global_fns, render_redirect_template};
|
use templates::{GUTENBERG_TERA, global_fns, render_redirect_template};
|
||||||
use front_matter::{SortBy, InsertAnchor};
|
use front_matter::{SortBy, InsertAnchor};
|
||||||
|
@ -67,7 +68,7 @@ pub struct Site {
|
||||||
pub tera: Tera,
|
pub tera: Tera,
|
||||||
live_reload: bool,
|
live_reload: bool,
|
||||||
output_path: PathBuf,
|
output_path: PathBuf,
|
||||||
static_path: PathBuf,
|
pub static_path: PathBuf,
|
||||||
pub tags: Option<Taxonomy>,
|
pub tags: Option<Taxonomy>,
|
||||||
pub categories: Option<Taxonomy>,
|
pub categories: Option<Taxonomy>,
|
||||||
/// A map of all .md files (section and pages) and their permalink
|
/// A map of all .md files (section and pages) and their permalink
|
||||||
|
@ -80,14 +81,29 @@ impl Site {
|
||||||
/// Passing in a path is only used in tests
|
/// Passing in a path is only used in tests
|
||||||
pub fn new<P: AsRef<Path>>(path: P, config_file: &str) -> Result<Site> {
|
pub fn new<P: AsRef<Path>>(path: P, config_file: &str) -> Result<Site> {
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
|
let config = get_config(path, config_file);
|
||||||
|
|
||||||
let tpl_glob = format!("{}/{}", path.to_string_lossy().replace("\\", "/"), "templates/**/*.*ml");
|
let tpl_glob = format!("{}/{}", path.to_string_lossy().replace("\\", "/"), "templates/**/*.*ml");
|
||||||
let mut tera = Tera::new(&tpl_glob).chain_err(|| "Error parsing templates")?;
|
let mut tera = Tera::new(&tpl_glob).chain_err(|| "Error parsing templates")?;
|
||||||
tera.extend(&GUTENBERG_TERA)?;
|
tera.extend(&GUTENBERG_TERA)?;
|
||||||
|
|
||||||
|
if let Some(ref theme) = config.theme {
|
||||||
|
// Test that the {templates,static} 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);
|
||||||
|
}
|
||||||
|
if !theme_path.join("static").exists() {
|
||||||
|
bail!("Theme `{}` is missing a static folder", theme);
|
||||||
|
}
|
||||||
|
let theme_tpl_glob = format!("{}/{}", path.to_string_lossy().replace("\\", "/"), "themes/**/*.html");
|
||||||
|
let tera_themes = Tera::new(&theme_tpl_glob).chain_err(|| "Error parsing templates from themes")?;
|
||||||
|
tera.extend(&tera_themes)?;
|
||||||
|
}
|
||||||
|
|
||||||
let site = Site {
|
let site = Site {
|
||||||
base_path: path.to_path_buf(),
|
base_path: path.to_path_buf(),
|
||||||
config: get_config(path, config_file),
|
config: config,
|
||||||
pages: HashMap::new(),
|
pages: HashMap::new(),
|
||||||
sections: HashMap::new(),
|
sections: HashMap::new(),
|
||||||
tera: tera,
|
tera: tera,
|
||||||
|
@ -242,7 +258,7 @@ impl Site {
|
||||||
|
|
||||||
if render {
|
if render {
|
||||||
let insert_anchor = self.find_parent_section_insert_anchor(&self.pages[&path].file.parent);
|
let insert_anchor = self.find_parent_section_insert_anchor(&self.pages[&path].file.parent);
|
||||||
let mut page = self.pages.get_mut(&path).unwrap();
|
let page = self.pages.get_mut(&path).unwrap();
|
||||||
page.render_markdown(&self.permalinks, &self.tera, &self.config, insert_anchor)?;
|
page.render_markdown(&self.permalinks, &self.tera, &self.config, insert_anchor)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,7 +275,7 @@ impl Site {
|
||||||
let prev = self.sections.insert(section.file.path.clone(), section);
|
let prev = self.sections.insert(section.file.path.clone(), section);
|
||||||
|
|
||||||
if render {
|
if render {
|
||||||
let mut section = self.sections.get_mut(&path).unwrap();
|
let section = self.sections.get_mut(&path).unwrap();
|
||||||
section.render_markdown(&self.permalinks, &self.tera, &self.config)?;
|
section.render_markdown(&self.permalinks, &self.tera, &self.config)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,9 +369,9 @@ impl Site {
|
||||||
html
|
html
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy static file to public directory.
|
/// Copy the file at the given path into the public folder
|
||||||
pub fn copy_static_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
|
pub fn copy_static_file<P: AsRef<Path>>(&self, path: P, base_path: &PathBuf) -> Result<()> {
|
||||||
let relative_path = path.as_ref().strip_prefix(&self.static_path).unwrap();
|
let relative_path = path.as_ref().strip_prefix(base_path).unwrap();
|
||||||
let target_path = self.output_path.join(relative_path);
|
let target_path = self.output_path.join(relative_path);
|
||||||
if let Some(parent_directory) = target_path.parent() {
|
if let Some(parent_directory) = target_path.parent() {
|
||||||
create_dir_all(parent_directory)?;
|
create_dir_all(parent_directory)?;
|
||||||
|
@ -364,24 +380,36 @@ impl Site {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy the content of the `static` folder into the `public` folder
|
/// Copy the content of the given folder into the `public` folder
|
||||||
pub fn copy_static_directory(&self) -> Result<()> {
|
fn copy_static_directory(&self, path: &PathBuf) -> Result<()> {
|
||||||
for entry in WalkDir::new(&self.static_path).into_iter().filter_map(|e| e.ok()) {
|
for entry in WalkDir::new(path).into_iter().filter_map(|e| e.ok()) {
|
||||||
let relative_path = entry.path().strip_prefix(&self.static_path).unwrap();
|
let relative_path = entry.path().strip_prefix(path).unwrap();
|
||||||
let target_path = self.output_path.join(relative_path);
|
let target_path = self.output_path.join(relative_path);
|
||||||
|
|
||||||
if entry.path().is_dir() {
|
if entry.path().is_dir() {
|
||||||
if !target_path.exists() {
|
if !target_path.exists() {
|
||||||
create_directory(&target_path)?;
|
create_directory(&target_path)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let entry_fullpath = self.base_path.join(entry.path());
|
let entry_fullpath = self.base_path.join(entry.path());
|
||||||
self.copy_static_file(entry_fullpath)?;
|
self.copy_static_file(entry_fullpath, path)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Copy the main `static` folder and the theme `static` folder if a theme is used
|
||||||
|
pub fn copy_static_directories(&self) -> Result<()> {
|
||||||
|
// The user files will overwrite the theme files
|
||||||
|
if let Some(ref theme) = self.config.theme {
|
||||||
|
self.copy_static_directory(
|
||||||
|
&self.base_path.join("themes").join(theme).join("static")
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
self.copy_static_directory(&self.static_path)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Deletes the `public` directory if it exists
|
/// Deletes the `public` directory if it exists
|
||||||
pub fn clean(&self) -> Result<()> {
|
pub fn clean(&self) -> Result<()> {
|
||||||
if self.output_path.exists() {
|
if self.output_path.exists() {
|
||||||
|
@ -440,17 +468,24 @@ impl Site {
|
||||||
self.render_categories()?;
|
self.render_categories()?;
|
||||||
self.render_tags()?;
|
self.render_tags()?;
|
||||||
|
|
||||||
if self.config.compile_sass.unwrap() {
|
if let Some(ref theme) = self.config.theme {
|
||||||
self.compile_sass()?;
|
let theme_path = self.base_path.join("themes").join(theme);
|
||||||
|
if theme_path.join("sass").exists() {
|
||||||
|
self.compile_sass(&theme_path)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.copy_static_directory()
|
if self.config.compile_sass.unwrap() {
|
||||||
|
self.compile_sass(&self.base_path)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.copy_static_directories()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_sass(&self) -> Result<()> {
|
pub fn compile_sass(&self, base_path: &PathBuf) -> Result<()> {
|
||||||
ensure_directory_exists(&self.output_path)?;
|
ensure_directory_exists(&self.output_path)?;
|
||||||
|
|
||||||
let base_path = self.base_path.to_string_lossy().replace("\\", "/");
|
let base_path = base_path.to_string_lossy().replace("\\", "/");
|
||||||
let sass_glob = format!("{}/{}", base_path, "sass/**/*.scss");
|
let sass_glob = format!("{}/{}", base_path, "sass/**/*.scss");
|
||||||
let files = glob(&sass_glob)
|
let files = glob(&sass_glob)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -495,7 +530,7 @@ impl Site {
|
||||||
ensure_directory_exists(&self.output_path)?;
|
ensure_directory_exists(&self.output_path)?;
|
||||||
create_file(
|
create_file(
|
||||||
&self.output_path.join("robots.txt"),
|
&self.output_path.join("robots.txt"),
|
||||||
&self.tera.render("robots.txt", &Context::new())?
|
&render_template("robots.txt", &self.tera, &Context::new(), self.config.theme.clone())?
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,7 +617,7 @@ impl Site {
|
||||||
}
|
}
|
||||||
context.add("tags", &tags);
|
context.add("tags", &tags);
|
||||||
|
|
||||||
let sitemap = self.tera.render("sitemap.xml", &context)?;
|
let sitemap = &render_template("sitemap.xml", &self.tera, &context, self.config.theme.clone())?;
|
||||||
|
|
||||||
create_file(&self.output_path.join("sitemap.xml"), &sitemap)?;
|
create_file(&self.output_path.join("sitemap.xml"), &sitemap)?;
|
||||||
|
|
||||||
|
@ -616,9 +651,9 @@ impl Site {
|
||||||
};
|
};
|
||||||
context.add("feed_url", &rss_feed_url);
|
context.add("feed_url", &rss_feed_url);
|
||||||
|
|
||||||
let sitemap = self.tera.render("rss.xml", &context)?;
|
let feed = &render_template("rss.xml", &self.tera, &context, self.config.theme.clone())?;
|
||||||
|
|
||||||
create_file(&self.output_path.join("rss.xml"), &sitemap)?;
|
create_file(&self.output_path.join("rss.xml"), &feed)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ highlight_code = true
|
||||||
compile_sass = true
|
compile_sass = true
|
||||||
generate_rss = true
|
generate_rss = true
|
||||||
rss_limit = 2
|
rss_limit = 2
|
||||||
|
theme = "sample"
|
||||||
|
|
||||||
[extra.author]
|
[extra.author]
|
||||||
name = "Vincent Prouillet"
|
name = "Vincent Prouillet"
|
||||||
|
|
3
components/site/test_site/themes/sample/sass/sample.scss
Normal file
3
components/site/test_site/themes/sample/sass/sample.scss
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
body {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
0
components/site/test_site/themes/sample/static/some.js
Normal file
0
components/site/test_site/themes/sample/static/some.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Hello
|
3
components/site/test_site/themes/sample/theme.toml
Normal file
3
components/site/test_site/themes/sample/theme.toml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
name = "sample"
|
||||||
|
|
||||||
|
[extra]
|
|
@ -100,7 +100,6 @@ fn can_build_site_without_live_reload() {
|
||||||
site.build().unwrap();
|
site.build().unwrap();
|
||||||
|
|
||||||
assert!(Path::new(&public).exists());
|
assert!(Path::new(&public).exists());
|
||||||
|
|
||||||
assert!(file_exists!(public, "index.html"));
|
assert!(file_exists!(public, "index.html"));
|
||||||
assert!(file_exists!(public, "sitemap.xml"));
|
assert!(file_exists!(public, "sitemap.xml"));
|
||||||
assert!(file_exists!(public, "robots.txt"));
|
assert!(file_exists!(public, "robots.txt"));
|
||||||
|
@ -130,6 +129,10 @@ fn can_build_site_without_live_reload() {
|
||||||
assert_eq!(file_exists!(public, "categories/index.html"), false);
|
assert_eq!(file_exists!(public, "categories/index.html"), false);
|
||||||
assert_eq!(file_exists!(public, "tags/index.html"), false);
|
assert_eq!(file_exists!(public, "tags/index.html"), false);
|
||||||
|
|
||||||
|
// Theme files are there
|
||||||
|
assert!(file_exists!(public, "sample.css"));
|
||||||
|
assert!(file_exists!(public, "some.js"));
|
||||||
|
|
||||||
// no live reload code
|
// no live reload code
|
||||||
assert_eq!(file_contains!(public, "index.html", "/livereload.js?port=1112&mindelay=10"), false);
|
assert_eq!(file_contains!(public, "index.html", "/livereload.js?port=1112&mindelay=10"), false);
|
||||||
|
|
||||||
|
|
|
@ -13,3 +13,4 @@ errors = { path = "../errors" }
|
||||||
config = { path = "../config" }
|
config = { path = "../config" }
|
||||||
content = { path = "../content" }
|
content = { path = "../content" }
|
||||||
front_matter = { path = "../front_matter" }
|
front_matter = { path = "../front_matter" }
|
||||||
|
utils = { path = "../utils" }
|
||||||
|
|
|
@ -7,6 +7,7 @@ extern crate errors;
|
||||||
extern crate config;
|
extern crate config;
|
||||||
extern crate content;
|
extern crate content;
|
||||||
extern crate front_matter;
|
extern crate front_matter;
|
||||||
|
extern crate utils;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ use config::Config;
|
||||||
use errors::{Result, ResultExt};
|
use errors::{Result, ResultExt};
|
||||||
use content::{Page, sort_pages};
|
use content::{Page, sort_pages};
|
||||||
use front_matter::SortBy;
|
use front_matter::SortBy;
|
||||||
|
use utils::templates::render_template;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
|
@ -139,7 +141,7 @@ impl Taxonomy {
|
||||||
context.add("current_url", &config.make_permalink(&format!("{}/{}", name, item.slug)));
|
context.add("current_url", &config.make_permalink(&format!("{}/{}", name, item.slug)));
|
||||||
context.add("current_path", &format!("/{}/{}", name, item.slug));
|
context.add("current_path", &format!("/{}/{}", name, item.slug));
|
||||||
|
|
||||||
tera.render(&format!("{}.html", name), &context)
|
render_template(&format!("{}.html", name), tera, &context, config.theme.clone())
|
||||||
.chain_err(|| format!("Failed to render {} page.", name))
|
.chain_err(|| format!("Failed to render {} page.", name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +153,7 @@ impl Taxonomy {
|
||||||
context.add("current_url", &config.make_permalink(&name));
|
context.add("current_url", &config.make_permalink(&name));
|
||||||
context.add("current_path", &name);
|
context.add("current_path", &name);
|
||||||
|
|
||||||
tera.render(&format!("{}.html", name), &context)
|
render_template(&format!("{}.html", name), tera, &context, config.theme.clone())
|
||||||
.chain_err(|| format!("Failed to render {} page.", name))
|
.chain_err(|| format!("Failed to render {} page.", name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@ pub mod filters;
|
||||||
pub mod global_fns;
|
pub mod global_fns;
|
||||||
|
|
||||||
use tera::{Tera, Context};
|
use tera::{Tera, Context};
|
||||||
use errors::{Result, ResultExt};
|
|
||||||
|
|
||||||
|
use errors::{Result, ResultExt};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref GUTENBERG_TERA: Tera = {
|
pub static ref GUTENBERG_TERA: Tera = {
|
||||||
|
|
|
@ -5,6 +5,7 @@ authors = ["Vincent Prouillet <vincent@wearewizards.io>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
errors = { path = "../errors" }
|
errors = { path = "../errors" }
|
||||||
|
tera = "0.10"
|
||||||
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -3,6 +3,8 @@ extern crate errors;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate tempdir;
|
extern crate tempdir;
|
||||||
|
extern crate tera;
|
||||||
|
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
pub mod site;
|
pub mod site;
|
||||||
|
pub mod templates;
|
||||||
|
|
21
components/utils/src/templates.rs
Normal file
21
components/utils/src/templates.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
use tera::{Tera, Context};
|
||||||
|
|
||||||
|
use errors::Result;
|
||||||
|
|
||||||
|
/// Renders the given template with the given context, but also ensures that, if the default file
|
||||||
|
/// is not found, it will look up for the equivalent template for the current theme if there is one
|
||||||
|
pub fn render_template(name: &str, tera: &Tera, context: &Context, theme: Option<String>) -> Result<String> {
|
||||||
|
if tera.templates.contains_key(name) {
|
||||||
|
return tera
|
||||||
|
.render(name, context)
|
||||||
|
.map_err(|e| e.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref t) = theme {
|
||||||
|
return tera
|
||||||
|
.render(&format!("{}/templates/{}", t, name), context)
|
||||||
|
.map_err(|e| e.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
bail!("Tried to render `{}` but the template wasn't found", name)
|
||||||
|
}
|
|
@ -180,12 +180,12 @@ pub fn serve(interface: &str, port: &str, config_file: &str) -> Result<()> {
|
||||||
(ChangeKind::StaticFiles, p) => {
|
(ChangeKind::StaticFiles, p) => {
|
||||||
if path.is_file() {
|
if path.is_file() {
|
||||||
console::info(&format!("-> Static file changes detected {}", path.display()));
|
console::info(&format!("-> Static file changes detected {}", path.display()));
|
||||||
rebuild_done_handling(&broadcaster, site.copy_static_file(&path), &p);
|
rebuild_done_handling(&broadcaster, site.copy_static_file(&path, &site.static_path), &p);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(ChangeKind::Sass, p) => {
|
(ChangeKind::Sass, p) => {
|
||||||
console::info(&format!("-> Sass file changed {}", path.display()));
|
console::info(&format!("-> Sass file changed {}", path.display()));
|
||||||
rebuild_done_handling(&broadcaster, site.compile_sass(), &p);
|
rebuild_done_handling(&broadcaster, site.compile_sass(&site.base_path), &p);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
console::report_elapsed_time(start);
|
console::report_elapsed_time(start);
|
||||||
|
|
Loading…
Reference in a new issue