@@ -7,6 +7,9 @@ | |||||
- Remove `section` from the `page` rendering context: this is too expensive. Use | - Remove `section` from the `page` rendering context: this is too expensive. Use | ||||
the global function `get_section` if you need to get it | the global function `get_section` if you need to get it | ||||
- Put back a 20 page limit on rss feed by default (configurable) | - Put back a 20 page limit on rss feed by default (configurable) | ||||
- Remove index page getting all sections: use the `get_section` global fn instead to | |||||
only get the ones you need | |||||
- Remove pages from pagers in pagination: they were not supposed to be there | |||||
## 0.0.7 (2017-06-19) | ## 0.0.7 (2017-06-19) | ||||
@@ -52,7 +52,7 @@ Each kind of page get their own variables: | |||||
// TODO: detail the schema of the variables | // TODO: detail the schema of the variables | ||||
- index.html: gets `section` representing the index section and all `sections` | |||||
- index.html: gets `section` representing the index section | |||||
- page.html: gets `page` that contains the data for that page | - page.html: gets `page` that contains the data for that page | ||||
- section.html: gets `section` that contains the data for pages in it and its subsections | - section.html: gets `section` that contains the data for pages in it and its subsections | ||||
- tags.html: gets `tags` | - tags.html: gets `tags` | ||||
@@ -65,6 +65,30 @@ the absolute URL of the current page and `current_path` that represents the path | |||||
If you want to know all the data present in a template content, simply put `{{ __tera_context }}` | If you want to know all the data present in a template content, simply put `{{ __tera_context }}` | ||||
in the templates and it will print it. | in the templates and it will print it. | ||||
Gutenberg also ships with 3 Tera global functions: | |||||
#### `get_page` | |||||
Takes a path to a `.md` file and returns the associated page | |||||
```jinja2 | |||||
{% set page = get_page(path="blog/page2.md") %} | |||||
``` | |||||
#### `get_section` | |||||
Takes a path to a `_index.md` file and returns the associated section | |||||
```jinja2 | |||||
{% set section = get_page(path="blog/_index.md") %} | |||||
``` | |||||
####` get_url` | |||||
Gets the permalink for a local file following the same convention as internal | |||||
link in markdown. | |||||
```jinja2 | |||||
{% set url = get_url(link="./blog/_index.md") %} | |||||
``` | |||||
### Static files | ### Static files | ||||
Everything in the `static` folder will be copied into the output directory as-is. | Everything in the `static` folder will be copied into the output directory as-is. | ||||
@@ -1,157 +0,0 @@ | |||||
//! Benchmarking loading/markdown rendering of generated sites of various sizes | |||||
#![feature(test)] | |||||
extern crate test; | |||||
extern crate gutenberg; | |||||
use std::env; | |||||
use gutenberg::Site; | |||||
#[bench] | |||||
fn bench_loading_small_blog(b: &mut test::Bencher) { | |||||
let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
path.push("benches"); | |||||
path.push("small-blog"); | |||||
let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
b.iter(|| site.load().unwrap()); | |||||
} | |||||
#[bench] | |||||
fn bench_loading_small_blog_with_syntax_highlighting(b: &mut test::Bencher) { | |||||
let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
path.push("benches"); | |||||
path.push("small-blog"); | |||||
let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
site.config.highlight_code = Some(true); | |||||
b.iter(|| site.load().unwrap()); | |||||
} | |||||
#[bench] | |||||
fn bench_loading_medium_blog(b: &mut test::Bencher) { | |||||
let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
path.push("benches"); | |||||
path.push("medium-blog"); | |||||
let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
b.iter(|| site.load().unwrap()); | |||||
} | |||||
#[bench] | |||||
fn bench_loading_medium_blog_with_syntax_highlighting(b: &mut test::Bencher) { | |||||
let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
path.push("benches"); | |||||
path.push("medium-blog"); | |||||
let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
site.config.highlight_code = Some(true); | |||||
b.iter(|| site.load().unwrap()); | |||||
} | |||||
#[bench] | |||||
fn bench_loading_big_blog(b: &mut test::Bencher) { | |||||
let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
path.push("benches"); | |||||
path.push("big-blog"); | |||||
let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
b.iter(|| site.load().unwrap()); | |||||
} | |||||
#[bench] | |||||
fn bench_loading_big_blog_with_syntax_highlighting(b: &mut test::Bencher) { | |||||
let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
path.push("benches"); | |||||
path.push("big-blog"); | |||||
let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
site.config.highlight_code = Some(true); | |||||
b.iter(|| site.load().unwrap()); | |||||
} | |||||
//#[bench] | |||||
//fn bench_loading_huge_blog(b: &mut test::Bencher) { | |||||
// let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
// path.push("benches"); | |||||
// path.push("huge-blog"); | |||||
// let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
// | |||||
// b.iter(|| site.load().unwrap()); | |||||
//} | |||||
// | |||||
//#[bench] | |||||
//fn bench_loading_huge_blog_with_syntax_highlighting(b: &mut test::Bencher) { | |||||
// let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
// path.push("benches"); | |||||
// path.push("huge-blog"); | |||||
// let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
// site.config.highlight_code = Some(true); | |||||
// | |||||
// b.iter(|| site.load().unwrap()); | |||||
//} | |||||
#[bench] | |||||
fn bench_loading_small_kb(b: &mut test::Bencher) { | |||||
let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
path.push("benches"); | |||||
path.push("small-kb"); | |||||
let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
b.iter(|| site.load().unwrap()); | |||||
} | |||||
#[bench] | |||||
fn bench_loading_small_kb_with_syntax_highlighting(b: &mut test::Bencher) { | |||||
let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
path.push("benches"); | |||||
path.push("small-kb"); | |||||
let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
site.config.highlight_code = Some(true); | |||||
b.iter(|| site.load().unwrap()); | |||||
} | |||||
#[bench] | |||||
fn bench_loading_medium_kb(b: &mut test::Bencher) { | |||||
let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
path.push("benches"); | |||||
path.push("medium-kb"); | |||||
let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
b.iter(|| site.load().unwrap()); | |||||
} | |||||
#[bench] | |||||
fn bench_loading_medium_kb_with_syntax_highlighting(b: &mut test::Bencher) { | |||||
let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
path.push("benches"); | |||||
path.push("medium-kb"); | |||||
let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
site.config.highlight_code = Some(true); | |||||
b.iter(|| site.load().unwrap()); | |||||
} | |||||
//#[bench] | |||||
//fn bench_loading_huge_kb(b: &mut test::Bencher) { | |||||
// let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
// path.push("benches"); | |||||
// path.push("huge-kb"); | |||||
// let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
// | |||||
// b.iter(|| site.load().unwrap()); | |||||
//} | |||||
// | |||||
//#[bench] | |||||
//fn bench_loading_huge_kb_with_syntax_highlighting(b: &mut test::Bencher) { | |||||
// let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
// path.push("benches"); | |||||
// path.push("huge-kb"); | |||||
// let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
// site.config.highlight_code = Some(true); | |||||
// | |||||
// b.iter(|| site.load().unwrap()); | |||||
//} |
@@ -1,27 +0,0 @@ | |||||
//! Benchmarking separate functions of Gutenberg | |||||
#![feature(test)] | |||||
extern crate test; | |||||
extern crate gutenberg; | |||||
extern crate tempdir; | |||||
use std::env; | |||||
use tempdir::TempDir; | |||||
use gutenberg::{Site, sort_pages, SortBy}; | |||||
fn setup_site(name: &str) -> Site { | |||||
let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
path.push("benches"); | |||||
path.push(name); | |||||
let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
site.load().unwrap(); | |||||
site | |||||
} | |||||
#[bench] | |||||
fn bench_sort_pages_medium_blog(b: &mut test::Bencher) { | |||||
let mut site = setup_site("huge-blog"); | |||||
let section = site.sections.values().next().unwrap().clone(); | |||||
b.iter(|| sort_pages(section.pages.clone(), SortBy::None)); | |||||
} |
@@ -1,73 +0,0 @@ | |||||
//! Benchmarking separate functions of Gutenberg | |||||
#![feature(test)] | |||||
extern crate test; | |||||
extern crate gutenberg; | |||||
extern crate tempdir; | |||||
use std::env; | |||||
use tempdir::TempDir; | |||||
use gutenberg::{Site, sort_pages}; | |||||
fn setup_site(name: &str) -> Site { | |||||
let mut path = env::current_dir().unwrap().to_path_buf(); | |||||
path.push("benches"); | |||||
path.push(name); | |||||
let mut site = Site::new(&path, "config.toml").unwrap(); | |||||
site.load().unwrap(); | |||||
site | |||||
} | |||||
#[bench] | |||||
fn bench_render_aliases(b: &mut test::Bencher) { | |||||
let mut site = setup_site("huge-blog"); | |||||
let tmp_dir = TempDir::new("benches").expect("create temp dir"); | |||||
let public = &tmp_dir.path().join("public"); | |||||
site.set_output_path(&public); | |||||
b.iter(|| site.render_aliases().unwrap()); | |||||
} | |||||
// | |||||
//#[bench] | |||||
//fn bench_render_sections_one_huge(b: &mut test::Bencher) { | |||||
// let mut site = setup_site("big-blog"); | |||||
// let tmp_dir = TempDir::new("benches").expect("create temp dir"); | |||||
// let public = &tmp_dir.path().join("public"); | |||||
// site.set_output_path(&public); | |||||
// b.iter(|| site.render_sections().unwrap()); | |||||
//} | |||||
#[bench] | |||||
fn bench_render_small_section_with_pages_and_pagination(b: &mut test::Bencher) { | |||||
let mut site = setup_site("small-blog"); | |||||
let tmp_dir = TempDir::new("benches").expect("create temp dir"); | |||||
let public = &tmp_dir.path().join("public"); | |||||
site.set_output_path(&public); | |||||
b.iter(|| site.render_section(site.sections.values().next().unwrap(), true).unwrap()); | |||||
} | |||||
#[bench] | |||||
fn bench_render_small_section_with_pages_and_no_pagination(b: &mut test::Bencher) { | |||||
let mut site = setup_site("small-blog"); | |||||
let tmp_dir = TempDir::new("benches").expect("create temp dir"); | |||||
let public = &tmp_dir.path().join("public"); | |||||
site.set_output_path(&public); | |||||
let mut section = site.sections.values().next().unwrap().clone(); | |||||
section.meta.paginate_by = None; | |||||
section.meta.template = None; | |||||
b.iter(|| site.render_section(§ion, true).unwrap()); | |||||
} | |||||
#[bench] | |||||
fn bench_sort_sections_pages_medium_blog(b: &mut test::Bencher) { | |||||
let mut site = setup_site("medium-blog"); | |||||
b.iter(|| site.sort_sections_pages(None)); | |||||
} | |||||
#[bench] | |||||
fn bench_sort_sections_pages_medium_kb(b: &mut test::Bencher) { | |||||
let mut site = setup_site("medium-kb"); | |||||
b.iter(|| site.sort_sections_pages(None)); | |||||
} |
@@ -104,7 +104,7 @@ impl Section { | |||||
} | } | ||||
/// Renders the page using the default layout, unless specified in front-matter | /// Renders the page using the default layout, unless specified in front-matter | ||||
pub fn render_html(&self, sections: HashMap<String, Section>, tera: &Tera, config: &Config) -> Result<String> { | |||||
pub fn render_html(&self, tera: &Tera, config: &Config) -> Result<String> { | |||||
let tpl_name = self.get_template_name(); | let tpl_name = self.get_template_name(); | ||||
let mut context = TeraContext::new(); | let mut context = TeraContext::new(); | ||||
@@ -112,9 +112,6 @@ impl Section { | |||||
context.add("section", self); | context.add("section", self); | ||||
context.add("current_url", &self.permalink); | context.add("current_url", &self.permalink); | ||||
context.add("current_path", &self.path); | context.add("current_path", &self.path); | ||||
if self.is_index() { | |||||
context.add("sections", §ions); | |||||
} | |||||
tera.render(&tpl_name, &context) | tera.render(&tpl_name, &context) | ||||
.chain_err(|| format!("Failed to render section '{}'", self.file.path.display())) | .chain_err(|| format!("Failed to render section '{}'", self.file.path.display())) | ||||
@@ -10,7 +10,6 @@ extern crate content; | |||||
extern crate front_matter; | extern crate front_matter; | ||||
use std::collections::HashMap; | use std::collections::HashMap; | ||||
use std::path::PathBuf; | |||||
use tera::{Tera, Context, to_value, Value}; | use tera::{Tera, Context, to_value, Value}; | ||||
@@ -41,6 +40,17 @@ impl<'a> Pager<'a> { | |||||
pages, | pages, | ||||
} | } | ||||
} | } | ||||
/// Returns a manually cloned Pager with the pages removed | |||||
/// for use as template context | |||||
fn clone_without_pages(&self) -> Pager<'a> { | |||||
Pager { | |||||
index: self.index, | |||||
permalink: self.permalink.clone(), | |||||
path: self.path.clone(), | |||||
pages: vec![], | |||||
} | |||||
} | |||||
} | } | ||||
#[derive(Clone, Debug, PartialEq)] | #[derive(Clone, Debug, PartialEq)] | ||||
@@ -125,7 +135,12 @@ impl<'a> Paginator<'a> { | |||||
paginator.insert("first", to_value(&self.section.permalink).unwrap()); | paginator.insert("first", to_value(&self.section.permalink).unwrap()); | ||||
let last_pager = &self.pagers[self.pagers.len() - 1]; | let last_pager = &self.pagers[self.pagers.len() - 1]; | ||||
paginator.insert("last", to_value(&last_pager.permalink).unwrap()); | paginator.insert("last", to_value(&last_pager.permalink).unwrap()); | ||||
paginator.insert("pagers", to_value(&self.pagers).unwrap()); | |||||
paginator.insert( | |||||
"pagers", | |||||
to_value( | |||||
&self.pagers.iter().map(|p| p.clone_without_pages()).collect::<Vec<_>>() | |||||
).unwrap() | |||||
); | |||||
// Variables for this specific page | // Variables for this specific page | ||||
if pager_index > 0 { | if pager_index > 0 { | ||||
@@ -147,16 +162,13 @@ impl<'a> Paginator<'a> { | |||||
paginator | paginator | ||||
} | } | ||||
pub fn render_pager(&self, pager: &Pager, config: &Config, sections: &HashMap<PathBuf, Section>, tera: &Tera) -> Result<String> { | |||||
pub fn render_pager(&self, pager: &Pager, config: &Config, tera: &Tera) -> Result<String> { | |||||
let mut context = Context::new(); | let mut context = Context::new(); | ||||
context.add("config", &config); | context.add("config", &config); | ||||
context.add("section", self.section); | context.add("section", self.section); | ||||
context.add("current_url", &pager.permalink); | context.add("current_url", &pager.permalink); | ||||
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)); | ||||
if self.section.is_index() { | |||||
context.add("section", §ions); | |||||
} | |||||
tera.render(&self.section.get_template_name(), &context) | tera.render(&self.section.get_template_name(), &context) | ||||
.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())) | ||||
@@ -2,12 +2,12 @@ | |||||
#![feature(test)] | #![feature(test)] | ||||
extern crate test; | extern crate test; | ||||
extern crate gutenberg; | |||||
extern crate site; | |||||
extern crate tempdir; | extern crate tempdir; | ||||
use std::env; | use std::env; | ||||
use gutenberg::Site; | |||||
use site::Site; | |||||
use tempdir::TempDir; | use tempdir::TempDir; | ||||
@@ -53,3 +53,14 @@ fn bench_render_categories(b: &mut test::Bencher) { | |||||
site.set_output_path(&public); | site.set_output_path(&public); | ||||
b.iter(|| site.render_categories().unwrap()); | b.iter(|| site.render_categories().unwrap()); | ||||
} | } | ||||
#[bench] | |||||
fn bench_render_paginated(b: &mut test::Bencher) { | |||||
let mut site = setup_site("medium-blog"); | |||||
let tmp_dir = TempDir::new("benches").expect("create temp dir"); | |||||
let public = &tmp_dir.path().join("public"); | |||||
site.set_output_path(&public); | |||||
let section = site.sections.values().collect::<Vec<_>>()[0]; | |||||
b.iter(|| site.render_paginated(&public, section)); | |||||
} |
@@ -589,17 +589,6 @@ impl Site { | |||||
Ok(()) | Ok(()) | ||||
} | } | ||||
/// Create a hashmap of paths to section | |||||
/// For example `content/posts/_index.md` key will be `posts` | |||||
/// The index section will always be called `index` so don't use a path such as | |||||
/// `content/index/_index.md` yourself | |||||
fn get_sections_map(&self) -> HashMap<String, Section> { | |||||
self.sections | |||||
.values() | |||||
.map(|s| (if s.is_index() { "index".to_string() } else { s.file.components.join("/") }, s.clone())) | |||||
.collect() | |||||
} | |||||
/// Renders a single section | /// Renders a single section | ||||
pub fn render_section(&self, section: &Section, render_pages: bool) -> Result<()> { | pub fn render_section(&self, section: &Section, render_pages: bool) -> Result<()> { | ||||
ensure_directory_exists(&self.output_path)?; | ensure_directory_exists(&self.output_path)?; | ||||
@@ -630,11 +619,7 @@ impl Site { | |||||
if section.meta.is_paginated() { | if section.meta.is_paginated() { | ||||
self.render_paginated(&output_path, section)?; | self.render_paginated(&output_path, section)?; | ||||
} else { | } else { | ||||
let output = section.render_html( | |||||
if section.is_index() { self.get_sections_map() } else { HashMap::new() }, | |||||
&self.tera, | |||||
&self.config, | |||||
)?; | |||||
let output = section.render_html(&self.tera, &self.config)?; | |||||
create_file(&output_path.join("index.html"), &self.inject_livereload(output))?; | create_file(&output_path.join("index.html"), &self.inject_livereload(output))?; | ||||
} | } | ||||
@@ -668,7 +653,7 @@ impl Site { | |||||
} | } | ||||
/// Renders a list of pages when the section/index is wanting pagination. | /// Renders a list of pages when the section/index is wanting pagination. | ||||
fn render_paginated(&self, output_path: &Path, section: &Section) -> Result<()> { | |||||
pub fn render_paginated(&self, output_path: &Path, section: &Section) -> Result<()> { | |||||
ensure_directory_exists(&self.output_path)?; | ensure_directory_exists(&self.output_path)?; | ||||
let paginate_path = match section.meta.paginate_path { | let paginate_path = match section.meta.paginate_path { | ||||
@@ -679,6 +664,7 @@ impl Site { | |||||
let paginator = Paginator::new(§ion.pages, section); | let paginator = Paginator::new(§ion.pages, section); | ||||
let folder_path = output_path.join(&paginate_path); | let folder_path = output_path.join(&paginate_path); | ||||
create_directory(&folder_path)?; | create_directory(&folder_path)?; | ||||
paginator | paginator | ||||
.pagers | .pagers | ||||
.par_iter() | .par_iter() | ||||
@@ -686,7 +672,7 @@ impl Site { | |||||
.map(|(i, pager)| { | .map(|(i, pager)| { | ||||
let page_path = folder_path.join(&format!("{}", i + 1)); | let page_path = folder_path.join(&format!("{}", i + 1)); | ||||
create_directory(&page_path)?; | create_directory(&page_path)?; | ||||
let output = paginator.render_pager(pager, &self.config, &self.sections, &self.tera)?; | |||||
let output = paginator.render_pager(pager, &self.config, &self.tera)?; | |||||
if i > 0 { | if i > 0 { | ||||
create_file(&page_path.join("index.html"), &self.inject_livereload(output))?; | create_file(&page_path.join("index.html"), &self.inject_livereload(output))?; | ||||
} else { | } else { | ||||