@@ -244,17 +244,6 @@ impl Section { | |||||
self.file.components.is_empty() | 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. | /// Creates a vectors of asset URLs. | ||||
fn serialize_assets(&self) -> Vec<String> { | fn serialize_assets(&self) -> Vec<String> { | ||||
self.assets.iter() | self.assets.iter() | ||||
@@ -101,7 +101,8 @@ impl Library { | |||||
self.sections.get_mut(*section_key).unwrap().pages.push(key); | 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 sections = self.paths_to_sections.clone(); | ||||
let mut sections_weight = HashMap::new(); | 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(); | let mut updates = HashMap::new(); | ||||
for (key, section) in &self.sections { | 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 { | let (sorted_pages, cannot_be_sorted_pages) = match section.meta.sort_by { | ||||
SortBy::None => continue, | SortBy::None => continue, | ||||
SortBy::Date => { | SortBy::Date => { | ||||
@@ -214,6 +208,17 @@ impl Library { | |||||
.collect() | .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> { | pub fn get_section(&self, path: &PathBuf) -> Option<&Section> { | ||||
self.sections.get(self.paths_to_sections.get(path).cloned().unwrap_or_default()) | self.sections.get(self.paths_to_sections.get(path).cloned().unwrap_or_default()) | ||||
} | } | ||||
@@ -34,6 +34,7 @@ impl<'a> SerializedTaxonomyItem<'a> { | |||||
slug: &item.slug, | slug: &item.slug, | ||||
permalink: &item.permalink, | permalink: &item.permalink, | ||||
pages, | pages, | ||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -12,19 +12,6 @@ use library::{Page, Section}; | |||||
use front_matter::{PageFrontMatter, SectionFrontMatter}; | 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)] | #[derive(Debug, Clone, Copy, PartialEq)] | ||||
pub enum PageChangesNeeded { | pub enum PageChangesNeeded { | ||||
/// Editing `taxonomies` | /// Editing `taxonomies` | ||||
@@ -106,7 +93,6 @@ fn delete_element(site: &mut Site, path: &Path, is_section: bool) -> Result<()> | |||||
if is_section { | if is_section { | ||||
if let Some(s) = site.library.remove_section(&path.to_path_buf()) { | if let Some(s) = site.library.remove_section(&path.to_path_buf()) { | ||||
site.permalinks.remove(&s.file.relative); | site.permalinks.remove(&s.file.relative); | ||||
site.populate_sections(); | |||||
} | } | ||||
} else if let Some(p) = site.library.remove_page(&path.to_path_buf()) { | } else if let Some(p) = site.library.remove_page(&path.to_path_buf()) { | ||||
site.permalinks.remove(&p.file.relative); | 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() { | if !p.meta.taxonomies.is_empty() { | ||||
site.populate_taxonomies()?; | 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 | // 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(); | site.register_tera_global_fns(); | ||||
// Deletion is something that doesn't happen all the time so we | // Deletion is something that doesn't happen all the time so we | ||||
// don't need to optimise it too much | // 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 | // Updating a section | ||||
Some(prev) => { | Some(prev) => { | ||||
// Copy the section data so we don't end up with an almost empty object | // 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 { | if site.library.get_section(&pathbuf).unwrap().meta == prev.meta { | ||||
// Front matter didn't change, only content did | // 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 | // Sort always comes first if present so the rendering will be fine | ||||
match changes { | match changes { | ||||
SectionChangesNeeded::Sort => { | SectionChangesNeeded::Sort => { | ||||
site.sort_sections_pages(Some(path)); | |||||
site.register_tera_global_fns(); | site.register_tera_global_fns(); | ||||
} | } | ||||
SectionChangesNeeded::Render => site.render_section(&site.library.get_section(&pathbuf).unwrap(), false)?, | 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 { | macro_rules! render_parent_section { | ||||
($site: expr, $path: expr) => { | ($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)?; | $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)? { | match site.add_page(page, true)? { | ||||
// Updating a page | // Updating a page | ||||
Some(prev) => { | Some(prev) => { | ||||
site.populate_sections(); | |||||
// Front matter didn't change, only content did | // Front matter didn't change, only content did | ||||
if site.library.get_page(&pathbuf).unwrap().meta == prev.meta { | if site.library.get_page(&pathbuf).unwrap().meta == prev.meta { | ||||
// Other than the page itself, the summary might be seen | // 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() { | if site.library.get_page(&pathbuf).unwrap().summary.is_some() { | ||||
render_parent_section!(site, path); | 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()); | return site.render_page(&site.library.get_page(&pathbuf).unwrap()); | ||||
} | } | ||||
// Front matter changed | // 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) { | 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 | // Sort always comes first if present so the rendering will be fine | ||||
match changes { | match changes { | ||||
PageChangesNeeded::Taxonomies => { | PageChangesNeeded::Taxonomies => { | ||||
site.populate_taxonomies()?; | site.populate_taxonomies()?; | ||||
site.register_tera_global_fns(); | |||||
site.render_taxonomies()?; | site.render_taxonomies()?; | ||||
} | } | ||||
PageChangesNeeded::Sort => { | 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(§ion_path)); | |||||
site.register_tera_global_fns(); | |||||
site.render_index()?; | site.render_index()?; | ||||
} | } | ||||
PageChangesNeeded::Render => { | PageChangesNeeded::Render => { | ||||
if !sections_populated { | |||||
site.populate_sections(); | |||||
sections_populated = true; | |||||
} | |||||
site.register_tera_global_fns(); | |||||
render_parent_section!(site, path); | render_parent_section!(site, path); | ||||
site.render_page(&site.library.get_page(&path.to_path_buf()).unwrap())?; | 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 => { | None => { | ||||
site.populate_sections(); | site.populate_sections(); | ||||
site.populate_taxonomies()?; | site.populate_taxonomies()?; | ||||
site.register_early_global_fns(); | |||||
site.register_tera_global_fns(); | site.register_tera_global_fns(); | ||||
// No need to optimise that yet, we can revisit if it becomes an issue | // No need to optimise that yet, we can revisit if it becomes an issue | ||||
site.build() | site.build() | ||||
@@ -357,12 +357,6 @@ impl Site { | |||||
self.library.populate_sections(); | 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 | /// Find all the tags and categories if it's asked in the config | ||||
pub fn populate_taxonomies(&mut self) -> Result<()> { | pub fn populate_taxonomies(&mut self) -> Result<()> { | ||||
if self.config.taxonomies.is_empty() { | if self.config.taxonomies.is_empty() { | ||||
@@ -3,11 +3,11 @@ title = "Section" | |||||
weight = 20 | 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). | 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. | 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 | 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 | 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 | ## Sorting | ||||
It is very common for Gutenberg templates to iterate over pages or sections | 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`, | 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: | create a list of links to the posts, a simple template might look like this: | ||||
```j2 | ```j2 | ||||
@@ -107,15 +107,15 @@ create a list of links to the posts, a simple template might look like this: | |||||
{% endfor %} | {% 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`, | 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 | `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. | 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 | 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. | The terminal will warn you if this is happening. | ||||
If several pages have the same date/weight/order, their permalink will be used | 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` | ### `date` | ||||
This will sort all pages by their `date` field, from the most recent (at the | 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 | 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. | earlier and later dates, respectively. | ||||
### `weight` | ### `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. | 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, | 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) | (at the bottom); pages sorted by date will be sorted from oldest (at the top) | ||||
to newest (at the bottom). | 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. | the `reverse` filter reverses this order. | ||||
**Note**: Unlike pages, permalinks will **not** be used to break ties between | **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 | **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. | iterate over your sections, you should always assign them weight. |