Skip to content

Hide pages and sections by adding hidden to frontmatter #2826

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions components/content/src/front_matter/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ pub struct PageFrontMatter {
pub datetime_tuple: Option<(i32, u8, u8)>,
/// Whether this page is a draft
pub draft: bool,
/// Whether this page is hidden
pub hidden: Option<bool>,
/// Prevent generation of a folder for current page
/// Defaults to `true`
#[serde(skip_serializing)]
Expand Down Expand Up @@ -155,6 +157,7 @@ impl Default for PageFrontMatter {
datetime: None,
datetime_tuple: None,
draft: false,
hidden: None,
render: true,
slug: None,
path: None,
Expand Down
3 changes: 3 additions & 0 deletions components/content/src/front_matter/section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ pub struct SectionFrontMatter {
/// to be used directly, like a posts section in a personal site
#[serde(skip_serializing)]
pub render: bool,
/// Whether to render all of the pages in this section, but not list them by defaulting their `hidden` to `true`
pub hidden: Option<bool>,
/// Whether to redirect when landing on that section. Defaults to `None`.
/// Useful for the same reason as `render` but when you don't want a 404 when
/// landing on the root section page
Expand Down Expand Up @@ -107,6 +109,7 @@ impl Default for SectionFrontMatter {
paginate_reversed: false,
paginate_path: DEFAULT_PAGINATE_PATH.to_string(),
render: true,
hidden: None,
redirect_to: None,
insert_anchor_links: None,
in_search_index: true,
Expand Down
31 changes: 30 additions & 1 deletion components/content/src/library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,36 @@ impl Library {
pub fn sort_section_pages(&mut self) {
let mut updates = AHashMap::new();
for (path, section) in &self.sections {
let pages: Vec<_> = section.pages.iter().map(|p| &self.pages[p]).collect();
let pages: Vec<_> = section
.pages
.iter()
.map(|p| &self.pages[p])
.filter(|page| {
!page
.ancestors
.iter()
.map(|ancestor| {
// Go through each ancestor in the library map,
// find it based on relative anchestor path
// and map the hidden (Option<bool>)
&self
.sections
.values()
.find(|section| &section.file.relative == ancestor)
.expect("to find ancestor of page")
.meta
.hidden
})
// Add page hidden meta to the chain, to fold into final value
.chain([page.meta.hidden].iter())
// Accumulate together as `accumulator || boolean` unless value explicitely
// set by a section's or page's frontmatter as `hidden = false`
.fold(false, |accumulator, boolean| match (accumulator, boolean) {
(_, Some(value)) => *value,
(value, None) => value,
})
})
.collect();
let (sorted_pages, cannot_be_sorted_pages) = match section.meta.sort_by {
SortBy::None => continue,
_ => sort_pages(&pages, section.meta.sort_by),
Expand Down
32 changes: 32 additions & 0 deletions components/content/src/pagination.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,41 @@ impl<'a> Paginator<'a> {

for p in &*self.all_pages {
let page = &library.pages[p];

if !page.meta.render {
continue;
}

// Check if any ancestor or page is hidden and allows any
// `hidden = false` to override prior explicit or
// inferred `hidden = true`
let is_hidden = page
.ancestors
.iter()
.map(|ancestor| {
// Go through each ancestor in the library map,
// find it based on relative anchestor path
// and map the hidden (Option<bool>)
library
.sections
.values()
.find(|section| &section.file.relative == ancestor)?
.meta
.hidden
})
// Add page hidden meta to the chain, to fold into final value
.chain([page.meta.hidden].into_iter())
// Accumulate together as `accumulator || boolean` unless value explicitely
// set by a section's or page's frontmatter as `hidden = false`
.fold(false, |accumulator, boolean| match (accumulator, boolean) {
(_, Some(value)) => value,
(value, None) => value,
});

if is_hidden {
continue;
}

current_page.push(SerializingPage::new(page, Some(library), false));

if current_page.len() == self.paginate_by {
Expand Down
25 changes: 25 additions & 0 deletions components/site/src/feeds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,31 @@ pub fn render_feeds(
let num_entries = site.config.feed_limit.unwrap_or(pages.len());
let p = pages
.iter()
.filter(|page| {
!page
.ancestors
.iter()
.map(|ancestor| {
// Go through each ancestor in the library map,
// find it based on relative anchestor path
// and map the hidden (Option<bool>)
&library
.sections
.values()
.find(|section| &section.file.relative == ancestor)
.expect("page to have ancestor")
.meta
.hidden
})
// Add page hidden meta to the chain, to fold into final value
.chain([page.meta.hidden].iter())
// Accumulate together as `accumulator || boolean` unless value explicitely
// set by a section's or page's frontmatter as `hidden = false`
.fold(false, |accumulator, boolean| match (accumulator, boolean) {
(_, Some(value)) => *value,
(value, None) => value,
})
})
.take(num_entries)
.map(|x| x.serialize_without_siblings(&library))
.collect::<Vec<_>>();
Expand Down
4 changes: 4 additions & 0 deletions docs/content/documentation/content/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ weight = 0
# A draft page is only loaded if the `--drafts` flag is passed to `zola build`, `zola serve` or `zola check`.
draft = false

# A hidden page is loaded and created, but won't be added to Paginators,
# set to true to hide page or false to override a parent section's `hidden = true`
hidden = false
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since hidden is a Option<bool> its good to default to false right? I was thinking of leaving it empty, implying the None state.
I assumed that people would get confused and since the None implies false with the inheritence rules specified above it, it should be fine!

Lemme know


# When set to "false" Zola will not create a separate folder with index.html inside for this page.
render = false

Expand Down
4 changes: 4 additions & 0 deletions docs/content/documentation/content/section.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ description = ""
# A draft section is only loaded if the `--drafts` flag is passed to `zola build`, `zola serve` or `zola check`.
draft = false

# A hidden section is loaded and created, but won't be added to Paginators,
# set to true to hide section's pages or false to override a parent section's `hidden = true`
hidden = false

# Used to sort pages by "date", "update_date", "title", "title_bytes", "weight", "slug" or "none". See below for more information.
sort_by = "none"

Expand Down