Rebuild more things now that it is more performant to do so

Fix #122
This commit is contained in:
Vincent Prouillet 2018-10-06 13:37:06 +02:00
parent cdcebaea26
commit 6843ec5c9c
6 changed files with 49 additions and 91 deletions

View file

@ -244,17 +244,6 @@ impl Section {
self.file.components.is_empty()
}
/// Returns all the paths of the pages belonging to that section
pub fn all_pages_path(&self) -> Vec<PathBuf> {
let paths = vec![];
paths
}
/// Whether the page given belongs to that section
pub fn is_child_page(&self, path: &PathBuf) -> bool {
false
}
/// Creates a vectors of asset URLs.
fn serialize_assets(&self) -> Vec<String> {
self.assets.iter()

View file

@ -101,7 +101,8 @@ impl Library {
self.sections.get_mut(*section_key).unwrap().pages.push(key);
}
}
self.sort_sections_pages(None);
self.sort_sections_pages();
let sections = self.paths_to_sections.clone();
let mut sections_weight = HashMap::new();
@ -120,17 +121,10 @@ impl Library {
}
}
/// Sort all sections pages unless `only` is set.
/// If `only` is set, only the pages of the section at that specific Path will be rendered.
pub fn sort_sections_pages(&mut self, only: Option<&Path>) {
/// Sort all sections pages
pub fn sort_sections_pages(&mut self) {
let mut updates = HashMap::new();
for (key, section) in &self.sections {
if let Some(p) = only {
if p != section.file.path {
continue;
}
}
let (sorted_pages, cannot_be_sorted_pages) = match section.meta.sort_by {
SortBy::None => continue,
SortBy::Date => {
@ -214,6 +208,17 @@ impl Library {
.collect()
}
pub fn find_parent_section(&self, path: &Path) -> Option<&Section> {
let page_key = self.paths_to_pages[path];
for s in self.sections.values() {
if s.pages.contains(&page_key) {
return Some(s)
}
}
None
}
pub fn get_section(&self, path: &PathBuf) -> Option<&Section> {
self.sections.get(self.paths_to_sections.get(path).cloned().unwrap_or_default())
}

View file

@ -34,6 +34,7 @@ impl<'a> SerializedTaxonomyItem<'a> {
slug: &item.slug,
permalink: &item.permalink,
pages,
}
}
}

View file

@ -12,19 +12,6 @@ use library::{Page, Section};
use front_matter::{PageFrontMatter, SectionFrontMatter};
/// Finds the section that contains the page given if there is one
pub fn find_parent_section<'a>(site: &'a Site, page: &Page) -> Option<&'a Section> {
for section in site.library.sections_values() {
// TODO: remove that, it's wrong now it should check the page key
if section.is_child_page(&page.file.path) {
return Some(section);
}
}
None
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PageChangesNeeded {
/// Editing `taxonomies`
@ -106,7 +93,6 @@ fn delete_element(site: &mut Site, path: &Path, is_section: bool) -> Result<()>
if is_section {
if let Some(s) = site.library.remove_section(&path.to_path_buf()) {
site.permalinks.remove(&s.file.relative);
site.populate_sections();
}
} else if let Some(p) = site.library.remove_page(&path.to_path_buf()) {
site.permalinks.remove(&p.file.relative);
@ -114,15 +100,11 @@ fn delete_element(site: &mut Site, path: &Path, is_section: bool) -> Result<()>
if !p.meta.taxonomies.is_empty() {
site.populate_taxonomies()?;
}
// if there is a parent section, we will need to re-render it
// most likely
if find_parent_section(site, &p).is_some() {
site.populate_sections();
}
}
site.populate_sections();
// Ensure we have our fn updated so it doesn't contain the permalink(s)/section/page deleted
site.register_early_global_fns();
site.register_tera_global_fns();
// Deletion is something that doesn't happen all the time so we
// don't need to optimise it too much
@ -137,9 +119,12 @@ fn handle_section_editing(site: &mut Site, path: &Path) -> Result<()> {
// Updating a section
Some(prev) => {
// Copy the section data so we don't end up with an almost empty object
site.library.get_section_mut(&pathbuf).unwrap().pages = prev.pages;
site.library.get_section_mut(&pathbuf).unwrap().ignored_pages = prev.ignored_pages;
site.library.get_section_mut(&pathbuf).unwrap().subsections = prev.subsections;
{
let s = site.library.get_section_mut(&pathbuf).unwrap();
s.pages = prev.pages;
s.ignored_pages = prev.ignored_pages;
s.subsections = prev.subsections;
}
if site.library.get_section(&pathbuf).unwrap().meta == prev.meta {
// Front matter didn't change, only content did
@ -152,7 +137,6 @@ fn handle_section_editing(site: &mut Site, path: &Path) -> Result<()> {
// Sort always comes first if present so the rendering will be fine
match changes {
SectionChangesNeeded::Sort => {
site.sort_sections_pages(Some(path));
site.register_tera_global_fns();
}
SectionChangesNeeded::Render => site.render_section(&site.library.get_section(&pathbuf).unwrap(), false)?,
@ -177,7 +161,7 @@ fn handle_section_editing(site: &mut Site, path: &Path) -> Result<()> {
macro_rules! render_parent_section {
($site: expr, $path: expr) => {
if let Some(s) = find_parent_section($site, &$site.library.get_page(&$path.to_path_buf()).unwrap()) {
if let Some(s) = $site.library.find_parent_section($path) {
$site.render_section(s, false)?;
};
}
@ -190,6 +174,8 @@ fn handle_page_editing(site: &mut Site, path: &Path) -> Result<()> {
match site.add_page(page, true)? {
// Updating a page
Some(prev) => {
site.populate_sections();
// Front matter didn't change, only content did
if site.library.get_page(&pathbuf).unwrap().meta == prev.meta {
// Other than the page itself, the summary might be seen
@ -197,42 +183,24 @@ fn handle_page_editing(site: &mut Site, path: &Path) -> Result<()> {
if site.library.get_page(&pathbuf).unwrap().summary.is_some() {
render_parent_section!(site, path);
}
// TODO: register_tera_global_fns is expensive as it involves lots of cloning
// I can't think of a valid usecase where you would need the content
// of a page through a global fn so it's commented out for now
// site.register_tera_global_fns();
site.register_tera_global_fns();
return site.render_page(&site.library.get_page(&pathbuf).unwrap());
}
// Front matter changed
let mut sections_populated = false;
for changes in find_page_front_matter_changes(&site.library.get_page(&pathbuf).unwrap().meta, &prev.meta) {
site.register_tera_global_fns();
// Sort always comes first if present so the rendering will be fine
match changes {
PageChangesNeeded::Taxonomies => {
site.populate_taxonomies()?;
site.register_tera_global_fns();
site.render_taxonomies()?;
}
PageChangesNeeded::Sort => {
let section_path = match find_parent_section(site, &site.library.get_page(&pathbuf).unwrap()) {
Some(s) => s.file.path.clone(),
None => continue // Do nothing if it's an orphan page
};
if !sections_populated {
site.populate_sections();
sections_populated = true;
}
site.sort_sections_pages(Some(&section_path));
site.register_tera_global_fns();
site.render_index()?;
}
PageChangesNeeded::Render => {
if !sections_populated {
site.populate_sections();
sections_populated = true;
}
site.register_tera_global_fns();
render_parent_section!(site, path);
site.render_page(&site.library.get_page(&path.to_path_buf()).unwrap())?;
}
@ -244,6 +212,7 @@ fn handle_page_editing(site: &mut Site, path: &Path) -> Result<()> {
None => {
site.populate_sections();
site.populate_taxonomies()?;
site.register_early_global_fns();
site.register_tera_global_fns();
// No need to optimise that yet, we can revisit if it becomes an issue
site.build()

View file

@ -357,12 +357,6 @@ impl Site {
self.library.populate_sections();
}
/// Sorts the pages of the section at the given path
/// By default will sort all sections but can be made to only sort a single one by providing a path
pub fn sort_sections_pages(&mut self, only: Option<&Path>) {
self.library.sort_sections_pages(only);
}
/// Find all the tags and categories if it's asked in the config
pub fn populate_taxonomies(&mut self) -> Result<()> {
if self.config.taxonomies.is_empty() {

View file

@ -3,11 +3,11 @@ title = "Section"
weight = 20
+++
A section is created whenever a folder (or subfolder) in the `content` section contains an
`_index.md` file. If a folder does not contain an `_index.md` file, no section will be
A section is created whenever a folder (or subfolder) in the `content` section contains an
`_index.md` file. If a folder does not contain an `_index.md` file, no section will be
created, but markdown files within that folder will still create pages (known as orphan pages).
The index page (i.e., the page displayed when a user browses to your `base_url`) is a section,
The index page (i.e., the page displayed when a user browses to your `base_url`) is a section,
which is created whether or not you add an `_index.md` file at the root of your `content` folder.
If you do not create an `_index.md` file in your content directory, this main content section will
not have any content or metadata. If you would like to add content or metadata, you can add an
@ -96,9 +96,9 @@ by setting the `paginate_path` variable, which defaults to `page`.
## Sorting
It is very common for Gutenberg templates to iterate over pages or sections
to display all pages/sections a given directory. Consider a very simple
to display all pages/sections a given directory. Consider a very simple
example: a `blog` directory with three files: `blog/Post_1.md`,
`blog/Post_2.md`, and `blog/Post_3.md`. To iterate over these posts and
`blog/Post_2.md`, and `blog/Post_3.md`. To iterate over these posts and
create a list of links to the posts, a simple template might look like this:
```j2
@ -107,15 +107,15 @@ create a list of links to the posts, a simple template might look like this:
{% endfor %}
```
This would iterate over the posts, and would do so in a specific order
based on the `sort_by` variable set in the `_index.md` page for the
This would iterate over the posts, and would do so in a specific order
based on the `sort_by` variable set in the `_index.md` page for the
containing section. The `sort_by` variable can be given three values: `date`,
`weight`, and `none`. If no `sort_by` method is set, the pages will be
sorted in the `none` order, which is not intended to be used for sorted content.
Any page that is missing the data it needs to be sorted will be ignored and
won't be rendered. For example, if a page is missing the date variable the
containing section sets `sort_by = "date"`, then that page will be ignored.
won't be rendered. For example, if a page is missing the date variable the
containing section sets `sort_by = "date"`, then that page will be ignored.
The terminal will warn you if this is happening.
If several pages have the same date/weight/order, their permalink will be used
@ -127,18 +127,18 @@ The `sort_by` front-matter variable can have the following values:
### `date`
This will sort all pages by their `date` field, from the most recent (at the
top of the list) to the oldest (at the bottom of the list). Each page will
get `page.earlier` and `page.later` variables that contain the pages with
get `page.earlier` and `page.later` variables that contain the pages with
earlier and later dates, respectively.
### `weight`
This will be sort all pages by their `weight` field, from lightest weight
(at the top of the list) to heaviest (at the bottom of the list). Each
page gets `page.lighter` and `page.heavier` variables that contain the
This will be sort all pages by their `weight` field, from lightest weight
(at the top of the list) to heaviest (at the bottom of the list). Each
page gets `page.lighter` and `page.heavier` variables that contain the
pages with lighter and heavier weights, respectively.
When iterating through pages, you may wish to use the Tera `reverse` filter,
When iterating through pages, you may wish to use the Tera `reverse` filter,
which reverses the order of the pages. Thus, after using the `reverse` filter,
pages sorted by weight will be sorted from lightest (at the top) to heaviest
pages sorted by weight will be sorted from lightest (at the top) to heaviest
(at the bottom); pages sorted by date will be sorted from oldest (at the top)
to newest (at the bottom).
@ -153,8 +153,8 @@ the top of the list and the heaviest (highest `weight`) will be at the top;
the `reverse` filter reverses this order.
**Note**: Unlike pages, permalinks will **not** be used to break ties between
equally weighted sections. Thus, if the `weight` variable for your section is not set (or if it
is set in a way that produces ties), then your sections will be sorted in
equally weighted sections. Thus, if the `weight` variable for your section is not set (or if it
is set in a way that produces ties), then your sections will be sorted in
**random** order. Moreover, that order is determined at build time and will
change with each site rebuild. Thus, if there is any chance that you will
change with each site rebuild. Thus, if there is any chance that you will
iterate over your sections, you should always assign them weight.