Merge pull request #352 from codesections/delete_order

Remove `order` and add `heavier`/`later`
This commit is contained in:
Vincent Prouillet 2018-07-31 15:08:58 +02:00 committed by GitHub
commit be439d7bfb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 210 additions and 199 deletions

View file

@ -11,7 +11,7 @@ use std::collections::HashMap;
use config::Config; use config::Config;
use tera::Tera; use tera::Tera;
use front_matter::{SortBy, InsertAnchor}; use front_matter::{SortBy, InsertAnchor};
use content::{Page, sort_pages, populate_previous_and_next_pages}; use content::{Page, sort_pages, populate_siblings};
fn create_pages(number: usize, sort_by: SortBy) -> Vec<Page> { fn create_pages(number: usize, sort_by: SortBy) -> Vec<Page> {
@ -128,17 +128,17 @@ fn bench_sorting_order(b: &mut test::Bencher) {
} }
#[bench] #[bench]
fn bench_populate_previous_and_next_pages(b: &mut test::Bencher) { fn bench_populate_siblings(b: &mut test::Bencher) {
let pages = create_pages(250, SortBy::Order); let pages = create_pages(250, SortBy::Order);
let (sorted_pages, _) = sort_pages(pages, SortBy::Order); let (sorted_pages, _) = sort_pages(pages, SortBy::Order);
b.iter(|| populate_previous_and_next_pages(&sorted_pages.clone())); b.iter(|| populate_siblings(&sorted_pages.clone()));
} }
#[bench] #[bench]
fn bench_page_render_html(b: &mut test::Bencher) { fn bench_page_render_html(b: &mut test::Bencher) {
let pages = create_pages(10, SortBy::Order); let pages = create_pages(10, SortBy::Order);
let (mut sorted_pages, _) = sort_pages(pages, SortBy::Order); let (mut sorted_pages, _) = sort_pages(pages, SortBy::Order);
sorted_pages = populate_previous_and_next_pages(&sorted_pages); sorted_pages = populate_siblings(&sorted_pages);
let config = Config::default(); let config = Config::default();
let mut tera = Tera::default(); let mut tera = Tera::default();

View file

@ -26,4 +26,4 @@ mod sorting;
pub use file_info::FileInfo; pub use file_info::FileInfo;
pub use page::Page; pub use page::Page;
pub use section::Section; pub use section::Section;
pub use sorting::{sort_pages, populate_previous_and_next_pages}; pub use sorting::{sort_pages, populate_siblings};

View file

@ -44,10 +44,14 @@ pub struct Page {
/// When <!-- more --> is found in the text, will take the content up to that part /// When <!-- more --> is found in the text, will take the content up to that part
/// as summary /// as summary
pub summary: Option<String>, pub summary: Option<String>,
/// The previous page, by whatever sorting is used for the index/section /// The earlier page, for pages sorted by date
pub previous: Option<Box<Page>>, pub earlier: Option<Box<Page>>,
/// The next page, by whatever sorting is used for the index/section /// The later page, for pages sorted by date
pub next: Option<Box<Page>>, pub later: Option<Box<Page>>,
/// The lighter page, for pages sorted by weight
pub lighter: Option<Box<Page>>,
/// The heavier page, for pages sorted by weight
pub heavier: Option<Box<Page>>,
/// Toc made from the headers of the markdown file /// Toc made from the headers of the markdown file
pub toc: Vec<Header>, pub toc: Vec<Header>,
} }
@ -68,8 +72,10 @@ impl Page {
components: vec![], components: vec![],
permalink: "".to_string(), permalink: "".to_string(),
summary: None, summary: None,
previous: None, earlier: None,
next: None, later: None,
lighter: None,
heavier: None,
toc: vec![], toc: vec![],
} }
} }
@ -229,8 +235,10 @@ impl Default for Page {
components: vec![], components: vec![],
permalink: "".to_string(), permalink: "".to_string(),
summary: None, summary: None,
previous: None, earlier: None,
next: None, later: None,
lighter: None,
heavier: None,
toc: vec![], toc: vec![],
} }
} }
@ -263,8 +271,10 @@ impl ser::Serialize for Page {
let (word_count, reading_time) = get_reading_analytics(&self.raw_content); let (word_count, reading_time) = get_reading_analytics(&self.raw_content);
state.serialize_field("word_count", &word_count)?; state.serialize_field("word_count", &word_count)?;
state.serialize_field("reading_time", &reading_time)?; state.serialize_field("reading_time", &reading_time)?;
state.serialize_field("previous", &self.previous)?; state.serialize_field("earlier", &self.earlier)?;
state.serialize_field("next", &self.next)?; state.serialize_field("later", &self.later)?;
state.serialize_field("lighter", &self.lighter)?;
state.serialize_field("heavier", &self.heavier)?;
state.serialize_field("toc", &self.toc)?; state.serialize_field("toc", &self.toc)?;
state.serialize_field("draft", &self.is_draft())?; state.serialize_field("draft", &self.is_draft())?;
let assets = self.serialize_assets(); let assets = self.serialize_assets();

View file

@ -7,7 +7,7 @@ use front_matter::SortBy;
/// Sort pages by the given criteria /// Sort pages by the given criteria
/// ///
/// Any pages that doesn't have a the required field when the sorting method is other than none /// Any pages that doesn't have a required field when the sorting method is other than none
/// will be ignored. /// will be ignored.
pub fn sort_pages(pages: Vec<Page>, sort_by: SortBy) -> (Vec<Page>, Vec<Page>) { pub fn sort_pages(pages: Vec<Page>, sort_by: SortBy) -> (Vec<Page>, Vec<Page>) {
if sort_by == SortBy::None { if sort_by == SortBy::None {
@ -19,7 +19,6 @@ pub fn sort_pages(pages: Vec<Page>, sort_by: SortBy) -> (Vec<Page>, Vec<Page>) {
.partition(|page| { .partition(|page| {
match sort_by { match sort_by {
SortBy::Date => page.meta.date.is_some(), SortBy::Date => page.meta.date.is_some(),
SortBy::Order => page.meta.order.is_some(),
SortBy::Weight => page.meta.weight.is_some(), SortBy::Weight => page.meta.weight.is_some(),
_ => unreachable!() _ => unreachable!()
} }
@ -36,16 +35,6 @@ pub fn sort_pages(pages: Vec<Page>, sort_by: SortBy) -> (Vec<Page>, Vec<Page>) {
} }
}) })
}, },
SortBy::Order => {
can_be_sorted.par_sort_unstable_by(|a, b| {
let ord = b.meta.order().cmp(&a.meta.order());
if ord == Ordering::Equal {
a.permalink.cmp(&b.permalink)
} else {
ord
}
})
},
SortBy::Weight => { SortBy::Weight => {
can_be_sorted.par_sort_unstable_by(|a, b| { can_be_sorted.par_sort_unstable_by(|a, b| {
let ord = a.meta.weight().cmp(&b.meta.weight()); let ord = a.meta.weight().cmp(&b.meta.weight());
@ -64,7 +53,7 @@ pub fn sort_pages(pages: Vec<Page>, sort_by: SortBy) -> (Vec<Page>, Vec<Page>) {
/// Horribly inefficient way to set previous and next on each pages that skips drafts /// Horribly inefficient way to set previous and next on each pages that skips drafts
/// So many clones /// So many clones
pub fn populate_previous_and_next_pages(input: &[Page]) -> Vec<Page> { pub fn populate_siblings(input: &[Page], sort_by: SortBy) -> Vec<Page> {
let mut res = Vec::with_capacity(input.len()); let mut res = Vec::with_capacity(input.len());
// The input is already sorted // The input is already sorted
@ -91,9 +80,20 @@ pub fn populate_previous_and_next_pages(input: &[Page]) -> Vec<Page> {
// Remove prev/next otherwise we serialise the whole thing... // Remove prev/next otherwise we serialise the whole thing...
let mut next_page = input[j].clone(); let mut next_page = input[j].clone();
next_page.previous = None;
next_page.next = None; match sort_by {
new_page.next = Some(Box::new(next_page)); SortBy::Weight => {
next_page.lighter = None;
next_page.heavier = None;
new_page.lighter = Some(Box::new(next_page));
},
SortBy::Date => {
next_page.earlier = None;
next_page.later = None;
new_page.later = Some(Box::new(next_page));
},
SortBy::None => {}
}
break; break;
} }
} }
@ -113,9 +113,20 @@ pub fn populate_previous_and_next_pages(input: &[Page]) -> Vec<Page> {
// Remove prev/next otherwise we serialise the whole thing... // Remove prev/next otherwise we serialise the whole thing...
let mut previous_page = input[j].clone(); let mut previous_page = input[j].clone();
previous_page.previous = None; match sort_by {
previous_page.next = None; SortBy::Weight => {
new_page.previous = Some(Box::new(previous_page)); previous_page.lighter = None;
previous_page.heavier = None;
new_page.heavier = Some(Box::new(previous_page));
},
SortBy::Date => {
previous_page.earlier = None;
previous_page.later = None;
new_page.earlier = Some(Box::new(previous_page));
},
SortBy::None => {
}
}
break; break;
} }
} }
@ -129,7 +140,7 @@ pub fn populate_previous_and_next_pages(input: &[Page]) -> Vec<Page> {
mod tests { mod tests {
use front_matter::{PageFrontMatter, SortBy}; use front_matter::{PageFrontMatter, SortBy};
use page::Page; use page::Page;
use super::{sort_pages, populate_previous_and_next_pages}; use super::{sort_pages, populate_siblings};
fn create_page_with_date(date: &str) -> Page { fn create_page_with_date(date: &str) -> Page {
let mut front_matter = PageFrontMatter::default(); let mut front_matter = PageFrontMatter::default();
@ -137,22 +148,6 @@ mod tests {
Page::new("content/hello.md", front_matter) Page::new("content/hello.md", front_matter)
} }
fn create_page_with_order(order: usize, filename: &str) -> Page {
let mut front_matter = PageFrontMatter::default();
front_matter.order = Some(order);
let mut p = Page::new("content/".to_string() + filename, front_matter);
// Faking a permalink to test sorting with equal order
p.permalink = filename.to_string();
p
}
fn create_draft_page_with_order(order: usize) -> Page {
let mut front_matter = PageFrontMatter::default();
front_matter.order = Some(order);
front_matter.draft = true;
Page::new("content/hello.md", front_matter)
}
fn create_page_with_weight(weight: usize) -> Page { fn create_page_with_weight(weight: usize) -> Page {
let mut front_matter = PageFrontMatter::default(); let mut front_matter = PageFrontMatter::default();
front_matter.weight = Some(weight); front_matter.weight = Some(weight);
@ -173,37 +168,6 @@ mod tests {
assert_eq!(pages[2].clone().meta.date.unwrap().to_string(), "2017-01-01"); assert_eq!(pages[2].clone().meta.date.unwrap().to_string(), "2017-01-01");
} }
#[test]
fn can_sort_by_order() {
let input = vec![
create_page_with_order(2, "hello.md"),
create_page_with_order(3, "hello2.md"),
create_page_with_order(1, "hello3.md"),
];
let (pages, _) = sort_pages(input, SortBy::Order);
// Should be sorted by order
assert_eq!(pages[0].clone().meta.order.unwrap(), 3);
assert_eq!(pages[1].clone().meta.order.unwrap(), 2);
assert_eq!(pages[2].clone().meta.order.unwrap(), 1);
}
#[test]
fn can_sort_by_order_uses_permalink_to_break_ties() {
let input = vec![
create_page_with_order(3, "b.md"),
create_page_with_order(3, "a.md"),
create_page_with_order(3, "c.md"),
];
let (pages, _) = sort_pages(input, SortBy::Order);
// Should be sorted by order
assert_eq!(pages[0].clone().meta.order.unwrap(), 3);
assert_eq!(pages[0].clone().permalink, "a.md");
assert_eq!(pages[1].clone().meta.order.unwrap(), 3);
assert_eq!(pages[1].clone().permalink, "b.md");
assert_eq!(pages[2].clone().meta.order.unwrap(), 3);
assert_eq!(pages[2].clone().permalink, "c.md");
}
#[test] #[test]
fn can_sort_by_weight() { fn can_sort_by_weight() {
let input = vec![ let input = vec![
@ -221,80 +185,48 @@ mod tests {
#[test] #[test]
fn can_sort_by_none() { fn can_sort_by_none() {
let input = vec![ let input = vec![
create_page_with_order(2, "a.md"), create_page_with_weight(2),
create_page_with_order(3, "a.md"), create_page_with_weight(3),
create_page_with_order(1, "a.md"), create_page_with_weight(1),
]; ];
let (pages, _) = sort_pages(input, SortBy::None); let (pages, _) = sort_pages(input, SortBy::None);
// Should be sorted by date assert_eq!(pages[0].clone().meta.weight.unwrap(), 2);
assert_eq!(pages[0].clone().meta.order.unwrap(), 2); assert_eq!(pages[1].clone().meta.weight.unwrap(), 3);
assert_eq!(pages[1].clone().meta.order.unwrap(), 3); assert_eq!(pages[2].clone().meta.weight.unwrap(), 1);
assert_eq!(pages[2].clone().meta.order.unwrap(), 1);
} }
#[test] #[test]
fn ignore_page_with_missing_field() { fn ignore_page_with_missing_field() {
let input = vec![ let input = vec![
create_page_with_order(2, "a.md"), create_page_with_weight(2),
create_page_with_order(3, "a.md"), create_page_with_weight(3),
create_page_with_date("2019-01-01"), create_page_with_date("2019-01-01"),
]; ];
let (pages, unsorted) = sort_pages(input, SortBy::Order); let (pages, unsorted) = sort_pages(input, SortBy::Weight);
assert_eq!(pages.len(), 2); assert_eq!(pages.len(), 2);
assert_eq!(unsorted.len(), 1); assert_eq!(unsorted.len(), 1);
} }
#[test] #[test]
fn can_populate_previous_and_next_pages() { fn can_populate_siblings() {
let input = vec![ let input = vec![
create_page_with_order(1, "a.md"), create_page_with_weight(1),
create_page_with_order(2, "b.md"), create_page_with_weight(2),
create_page_with_order(3, "a.md"), create_page_with_weight(3),
]; ];
let pages = populate_previous_and_next_pages(&input); let pages = populate_siblings(&input, SortBy::Weight);
assert!(pages[0].clone().next.is_none()); assert!(pages[0].clone().lighter.is_none());
assert!(pages[0].clone().previous.is_some()); assert!(pages[0].clone().heavier.is_some());
assert_eq!(pages[0].clone().previous.unwrap().meta.order.unwrap(), 2); assert_eq!(pages[0].clone().heavier.unwrap().meta.weight.unwrap(), 2);
assert!(pages[1].clone().next.is_some()); assert!(pages[1].clone().heavier.is_some());
assert!(pages[1].clone().previous.is_some()); assert!(pages[1].clone().lighter.is_some());
assert_eq!(pages[1].clone().previous.unwrap().meta.order.unwrap(), 3); assert_eq!(pages[1].clone().lighter.unwrap().meta.weight.unwrap(), 1);
assert_eq!(pages[1].clone().next.unwrap().meta.order.unwrap(), 1); assert_eq!(pages[1].clone().heavier.unwrap().meta.weight.unwrap(), 3);
assert!(pages[2].clone().next.is_some()); assert!(pages[2].clone().lighter.is_some());
assert!(pages[2].clone().previous.is_none()); assert!(pages[2].clone().heavier.is_none());
assert_eq!(pages[2].clone().next.unwrap().meta.order.unwrap(), 2); assert_eq!(pages[2].clone().lighter.unwrap().meta.weight.unwrap(), 2);
}
#[test]
fn can_populate_previous_and_next_pages_skip_drafts() {
let input = vec![
create_draft_page_with_order(0),
create_page_with_order(1, "a.md"),
create_page_with_order(2, "b.md"),
create_page_with_order(3, "c.md"),
create_draft_page_with_order(4),
];
let pages = populate_previous_and_next_pages(&input);
assert!(pages[0].clone().next.is_none());
assert!(pages[0].clone().previous.is_none());
assert!(pages[1].clone().next.is_none());
assert!(pages[1].clone().previous.is_some());
assert_eq!(pages[1].clone().previous.unwrap().meta.order.unwrap(), 2);
assert!(pages[2].clone().next.is_some());
assert!(pages[2].clone().previous.is_some());
assert_eq!(pages[2].clone().previous.unwrap().meta.order.unwrap(), 3);
assert_eq!(pages[2].clone().next.unwrap().meta.order.unwrap(), 1);
assert!(pages[3].clone().next.is_some());
assert!(pages[3].clone().previous.is_none());
assert_eq!(pages[3].clone().next.unwrap().meta.order.unwrap(), 2);
assert!(pages[4].clone().next.is_none());
assert!(pages[4].clone().previous.is_none());
} }
} }

View file

@ -30,8 +30,6 @@ lazy_static! {
pub enum SortBy { pub enum SortBy {
/// Most recent to oldest /// Most recent to oldest
Date, Date,
/// Lower order comes last
Order,
/// Lower weight comes first /// Lower weight comes first
Weight, Weight,
/// No sorting /// No sorting

View file

@ -79,7 +79,7 @@ fn can_rebuild_after_simple_change_to_page_content() {
let file_path = edit_file!(site_path, "content/rebuild/first.md", br#" let file_path = edit_file!(site_path, "content/rebuild/first.md", br#"
+++ +++
title = "first" title = "first"
order = 1 weight = 1
date = 2017-01-01 date = 2017-01-01
+++ +++
@ -97,7 +97,7 @@ fn can_rebuild_after_title_change_page_global_func_usage() {
let file_path = edit_file!(site_path, "content/rebuild/first.md", br#" let file_path = edit_file!(site_path, "content/rebuild/first.md", br#"
+++ +++
title = "Premier" title = "Premier"
order = 10 weight = 10
date = 2017-01-01 date = 2017-01-01
+++ +++
@ -115,12 +115,12 @@ fn can_rebuild_after_sort_change_in_section() {
let file_path = edit_file!(site_path, "content/rebuild/_index.md", br#" let file_path = edit_file!(site_path, "content/rebuild/_index.md", br#"
+++ +++
paginate_by = 1 paginate_by = 1
sort_by = "order" sort_by = "weight"
template = "rebuild.html" template = "rebuild.html"
+++ +++
"#); "#);
let res = after_content_change(&mut site, &file_path); let res = after_content_change(&mut site, &file_path);
assert!(res.is_ok()); assert!(res.is_ok());
assert!(file_contains!(site_path, "public/rebuild/index.html", "<h1>second</h1><h1>first</h1>")); assert!(file_contains!(site_path, "public/rebuild/index.html", "<h1>first</h1><h1>second</h1>"));
} }

View file

@ -36,7 +36,7 @@ use config::{Config, get_config};
use utils::fs::{create_file, copy_directory, create_directory, ensure_directory_exists}; use utils::fs::{create_file, copy_directory, create_directory, ensure_directory_exists};
use utils::templates::{render_template, rewrite_theme_paths}; use utils::templates::{render_template, rewrite_theme_paths};
use utils::net::get_available_port; use utils::net::get_available_port;
use content::{Page, Section, populate_previous_and_next_pages, sort_pages}; use content::{Page, Section, populate_siblings, 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};
use taxonomies::{Taxonomy, find_taxonomies}; use taxonomies::{Taxonomy, find_taxonomies};
@ -401,7 +401,7 @@ impl Site {
} }
let pages = mem::replace(&mut section.pages, vec![]); let pages = mem::replace(&mut section.pages, vec![]);
let (sorted_pages, cannot_be_sorted_pages) = sort_pages(pages, section.meta.sort_by); let (sorted_pages, cannot_be_sorted_pages) = sort_pages(pages, section.meta.sort_by);
section.pages = populate_previous_and_next_pages(&sorted_pages); section.pages = populate_siblings(&sorted_pages, section.meta.sort_by);
section.ignored_pages = cannot_be_sorted_pages; section.ignored_pages = cannot_be_sorted_pages;
} }
} }

View file

@ -6,6 +6,22 @@ weight = 30
A page is any file ending with `.md` in the `content` directory, except files A page is any file ending with `.md` in the `content` directory, except files
named `_index.md`. named `_index.md`.
If a file ending with `.md` is named `index.md`, then it will generate a page
with the name of the containing folder (for example, `/content/about/index.md` would
create a page at `[base_url]/about`). (Note the lack of an underscore; if the file
were named `_index.md`, then it would create a **section** at `[base_url]/about`, as
discussed in the prior part of this documentation. But naming the file `index.md` will
create a **page** at `[base_url]/about`).
If the file is given any name *other* than `index.md` or `_index.md`, then it will
create a page with that name (without the `.md`). So naming a file in the root of your
content directory `about.md` would also create a page at `[base_url]/about`.
As you can see, creating an `about.md` file is exactly equivalent to creating an
`about/index.md` file. The only difference between the two methods is that creating
the `about` folder allows you to use asset colocation, as discussed in the
[Overview](./documentation/content/overview.md) section of this documentation.
## Front-matter ## Front-matter
The front-matter is a set of metadata embedded in a file. In Gutenberg, The front-matter is a set of metadata embedded in a file. In Gutenberg,
@ -13,7 +29,8 @@ it is at the beginning of the file, surrounded by `+++` and uses TOML.
While none of the front-matter variables are mandatory, the opening and closing `+++` are required. While none of the front-matter variables are mandatory, the opening and closing `+++` are required.
Here is an example page with all the variables available: Here is an example page with all the variables available. The values provided below are the default
values.
```md ```md
+++ +++
@ -22,8 +39,15 @@ description = ""
# The date of the post. # The date of the post.
# 2 formats are allowed: YYYY-MM-DD (2012-10-02) and RFC3339 (2002-10-02T15:00:00Z) # 2 formats are allowed: YYYY-MM-DD (2012-10-02) and RFC3339 (2002-10-02T15:00:00Z)
# Do not wrap dates in quotes, the line below only indicates that there is no default date # Do not wrap dates in quotes, the line below only indicates that there is no default date.
date = # If the section variable `sort_by` is set to `date`, then any page that lacks a `date`
# will not be rendered.
date =
# The weight as defined in the Section page
# If the section variable `sort_by` is set to `weight`, then any page that lacks a `weight`
# will not be rendered.
weight = 0
# A draft page will not be present in prev/next pagination # A draft page will not be present in prev/next pagination
draft = false draft = false
@ -38,28 +62,18 @@ slug = ""
# It should not start with a `/` and the slash will be removed if it does # It should not start with a `/` and the slash will be removed if it does
path = "" path = ""
# A dict of taxonomies: the key is the name of the taxonomy which must match # An array of strings allowing you to group pages with them
# one of the taxonomy defined in `config.toml` and the value is a list of tags = []
# strings
[taxonomies]
# The order as defined in the Section page # An overarching category name for that page, allowing you to group pages with it
order = 0 category = ""
# The weight as defined in the Section page # Use aliases if you are moving content but want to redirect previous URLs to the
weight = 0 # current one. This takes an array of path, not URLs.
# Use aliases if you are moving content but want to redirect previous URLs to the
# current one. Each element in the array of aliases may take one of two forms:
# * "some/alias/path", which will generate "some/alias/path/index.html"
# * "some/alias/path.html", which will generate "some/alias/path.html"
#
# The former is useful if your previous site had the form "example.com/some/alias/path",
# the latter is useful if your previous site had the form "example.com/some/alias/path.html"
aliases = [] aliases = []
# Whether the page should be in the search index. This is only used if # Whether the page should be in the search index. This is only used if
# `build_search_index` is set to true in the config and the parent section # `build_search_index` is set to true in the config and the parent section
# hasn't set `in_search_index` to false in its front-matter # hasn't set `in_search_index` to false in its front-matter
in_search_index = true in_search_index = true
@ -75,7 +89,7 @@ Some content
## Summary ## Summary
You can ask Gutenberg to create a summary if you only want to show the first You can ask Gutenberg to create a summary if you only want to show the first
paragraph of each page in a list for example. paragraph of each page in a list for example.
To do so, add <code>&lt;!-- more --&gt;</code> in your content at the point To do so, add <code>&lt;!-- more --&gt;</code> in your content at the point
@ -83,6 +97,6 @@ where you want the summary to end and the content up to that point will be also
available separately in the available separately in the
[template](./documentation/templates/pages-sections.md#page-variables). [template](./documentation/templates/pages-sections.md#page-variables).
An anchor link to this position named `continue-reading` is created so you can link An anchor link to this position named `continue-reading` is created so you can link
directly to it if needed for example: directly to it if needed for example:
`<a href="{{ page.permalink }}#continue-reading">Continue Reading</a>` `<a href="{{ page.permalink }}#continue-reading">Continue Reading</a>`

View file

@ -3,22 +3,32 @@ title = "Section"
weight = 20 weight = 20
+++ +++
A section is automatically created when a folder is found in the `content` section, unless it only A section is created whenever a folder (or subfolder) in the `content` section contains an
contains a `index.md` file and is actually a page with assets. `_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).
You can add `_index.md` file to a folder to augment a section and give it some metadata and/or content. 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.
The index page is actually a section created automatically like any other: you can add metadata If you do not create an `_index.md` file in your content directory, this main content section will
and content by adding `_index.md` at the root of the `content` folder. not have any content or metadata. If you would like to add content or metadata, you can add an
`_index.md` file at the root of the `content` folder and edit it just as you would edit any other
`_index.md` file; your `index.html` template will then have access to that content and metadata.
## Front-matter ## Front-matter
The `_index.md` file within a folder defines the content and metadata for that section. To set
the metadata, add front matter to the file.
The front-matter is a set of metadata embedded in a file. In Gutenberg, The front-matter is a set of metadata embedded in a file. In Gutenberg,
it is at the beginning of the file, surrounded by `+++` and uses TOML. it is at the beginning of the file, surrounded by `+++` and uses TOML.
After the closing `+++`, you can add content that will be parsed as markdown and will be available
to your templates through the `section.content` variable.
While none of the front-matter variables are mandatory, the opening and closing `+++` are required. While none of the front-matter variables are mandatory, the opening and closing `+++` are required.
Here is an example `_index.md` with all the variables available: Here is an example `_index.md` with all the variables available. The values provided below are the
default values.
```md ```md
@ -27,7 +37,7 @@ title = ""
description = "" description = ""
# Whether to sort by "date", "order", "weight" or "none". More on that below # Whether to sort pages by "date", "weight", or "none". More on that below
sort_by = "none" sort_by = "none"
# Used by the parent section to order its subsections. # Used by the parent section to order its subsections.
@ -83,22 +93,66 @@ You can also change the pagination path (the word displayed while paginated in t
by setting the `paginate_path` variable, which defaults to `page`. by setting the `paginate_path` variable, which defaults to `page`.
## Sorting ## Sorting
Sections' pages can be sorted three different ways, not counting the unsorted default and It is very common for Gutenberg templates to iterate over pages or sections
is enabled by setting the `sort_by` front-matter variable. 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
create a list of links to the posts, a simple template might look like this:
Any page that cannot be sorted, for example if missing the date variable while sorting by `date`, will be ignored and ```j2
won't be rendered. The terminal will warn you if this is happening. {% for post in section.pages %}
<h1><a href="{{ post.permalink }}">{{ post.title }}</a></h1>
{% endfor %}
```
If several pages have the same date/weight/order, their permalink will be used to break the tie following This would iterate over the posts, and would do so in a specific order
an alphabetical 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.
The terminal will warn you if this is happening.
If several pages have the same date/weight/order, their permalink will be used
to break the tie following an alphabetical order.
## Sorting Pages
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 to the oldest. 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
earlier and later dates, respectively.
### `weight` ### `weight`
This will be sort all pages by their `weight` field. Heavier weights fall at the bottom: 5 would be before 10. 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.
### `order` When iterating through pages, you may wish to use the Tera `reverse` filter,
This will be sort all pages by their `order` field. Order is the opposite of weight, think of it as enumerating which reverses the order of the pages. Thus, after using the `reverse` filter,
the content: this is my first post, my second, etc. A page with `order: 5` will appear after a page with `order: 10` in the sorted list. 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).
`reverse` has no effect on `page.later`/`page.earlier`/`page.heavier`/`page.lighter`.
## Sorting Subsections
Sorting sections is a bit less flexible: sections are always sorted by `weight`,
and do not have any variables that point to the next heavier/lighter sections.
Based on this, by default the lightest (lowest `weight`) subsections will be at
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
**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
iterate over your sections, you should always assign them weight.

View file

@ -32,9 +32,12 @@ extra: HashMap<String, Any>;
word_count: Number; word_count: Number;
// Based on https://help.medium.com/hc/en-us/articles/214991667-Read-time // Based on https://help.medium.com/hc/en-us/articles/214991667-Read-time
reading_time: Number; reading_time: Number;
// `previous` and `next` are only filled if the content can be sorted // `earlier` and `later` are only populated if the section variable `sort_by` is set to `date`
previous: Page?; earlier: Page?;
next: Page?; later: Page?;
// `heavier` and `lighter` are only populated if the section variable `sort_by` is set to `weight`
heavier: Page?;
lighter: Page?;
// See the Table of contents section below for more details // See the Table of contents section below for more details
toc: Array<Header>; toc: Array<Header>;
// Year/month/day is only set if the page has a date and month/day are 1-indexed // Year/month/day is only set if the page has a date and month/day are 1-indexed

View file

@ -1,6 +1,6 @@
+++ +++
title = "DevOps" title = "DevOps"
sort_by = "order" sort_by = "weight"
redirect_to = "posts/tutorials/devops/docker" redirect_to = "posts/tutorials/devops/docker"
weight = 10 weight = 10
+++ +++

View file

@ -1,6 +1,6 @@
+++ +++
title = "Docker" title = "Docker"
order = 1 weight = 1
date = 2017-01-01 date = 2017-01-01
+++ +++

View file

@ -1,6 +1,6 @@
+++ +++
title = "Nix" title = "Nix"
order = 2 weight = 2
date = 2017-01-01 date = 2017-01-01
+++ +++

View file

@ -1,5 +1,5 @@
+++ +++
title = "Programming" title = "Programming"
sort_by = "order" sort_by = "weight"
weight = 1 weight = 1
+++ +++

View file

@ -1,6 +1,6 @@
+++ +++
title = "Python tutorial" title = "Python tutorial"
order = 1 weight = 1
date = 2017-01-01 date = 2017-01-01
+++ +++

View file

@ -1,6 +1,6 @@
+++ +++
title = "Rust" title = "Rust"
order = 2 weight = 2
date = 2017-01-01 date = 2017-01-01
+++ +++

View file

@ -1,5 +1,5 @@
+++ +++
paginate_by = 1 paginate_by = 1
sort_by = "order" sort_by = "weight"
template = "rebuild.html" template = "rebuild.html"
+++ +++

View file

@ -1,6 +1,6 @@
+++ +++
title = "first" title = "first"
order = 10 weight = 10
date = 2017-01-01 date = 2017-01-01
+++ +++

View file

@ -1,6 +1,6 @@
+++ +++
title = "second" title = "second"
order = 100 weight = 100
date = 2016-01-01 date = 2016-01-01
+++ +++