Add new sorting: UpdateDate that sorts by meta.updated
. (#1452)
* Add new sorting: UpdateDate that sorts by `meta.updated`. * Use `max(created, updated)` for sort-by-update-date This prevents created but never updated articles from appearing at the end/not appearing at all.
This commit is contained in:
parent
b244bcdfbb
commit
f8c6ea2b00
|
@ -48,6 +48,8 @@ impl RawFrontMatter<'_> {
|
|||
pub enum SortBy {
|
||||
/// Most recent to oldest
|
||||
Date,
|
||||
/// Most recent to oldest
|
||||
UpdateDate,
|
||||
/// Sort by title
|
||||
Title,
|
||||
/// Lower weight comes first
|
||||
|
|
|
@ -20,6 +20,12 @@ pub struct PageFrontMatter {
|
|||
/// Updated date
|
||||
#[serde(default, deserialize_with = "from_toml_datetime")]
|
||||
pub updated: Option<String>,
|
||||
/// Chrono converted update datatime
|
||||
#[serde(default, skip_deserializing)]
|
||||
pub updated_datetime: Option<NaiveDateTime>,
|
||||
/// The converted update datetime into a (year, month, day) tuple
|
||||
#[serde(default, skip_deserializing)]
|
||||
pub updated_datetime_tuple: Option<(i32, u32, u32)>,
|
||||
/// Date if we want to order pages (ie blog post)
|
||||
#[serde(default, deserialize_with = "from_toml_datetime")]
|
||||
pub date: Option<String>,
|
||||
|
@ -107,6 +113,10 @@ impl PageFrontMatter {
|
|||
pub fn date_to_datetime(&mut self) {
|
||||
self.datetime = self.date.as_ref().map(|s| s.as_ref()).and_then(parse_datetime);
|
||||
self.datetime_tuple = self.datetime.map(|dt| (dt.year(), dt.month(), dt.day()));
|
||||
|
||||
self.updated_datetime = self.updated.as_ref().map(|s| s.as_ref()).and_then(parse_datetime);
|
||||
self.updated_datetime_tuple =
|
||||
self.updated_datetime.map(|dt| (dt.year(), dt.month(), dt.day()));
|
||||
}
|
||||
|
||||
pub fn weight(&self) -> usize {
|
||||
|
@ -120,6 +130,8 @@ impl Default for PageFrontMatter {
|
|||
title: None,
|
||||
description: None,
|
||||
updated: None,
|
||||
updated_datetime: None,
|
||||
updated_datetime_tuple: None,
|
||||
date: None,
|
||||
datetime: None,
|
||||
datetime_tuple: None,
|
||||
|
|
|
@ -60,6 +60,10 @@ pub struct Page {
|
|||
/// When <!-- more --> is found in the text, will take the content up to that part
|
||||
/// as summary
|
||||
pub summary: Option<String>,
|
||||
/// The earlier updated page, for pages sorted by updated date
|
||||
pub earlier_updated: Option<DefaultKey>,
|
||||
/// The later updated page, for pages sorted by updated date
|
||||
pub later_updated: Option<DefaultKey>,
|
||||
/// The earlier page, for pages sorted by date
|
||||
pub earlier: Option<DefaultKey>,
|
||||
/// The later page, for pages sorted by date
|
||||
|
|
|
@ -90,6 +90,8 @@ pub struct SerializingPage<'a> {
|
|||
lang: &'a str,
|
||||
lighter: Option<Box<SerializingPage<'a>>>,
|
||||
heavier: Option<Box<SerializingPage<'a>>>,
|
||||
earlier_updated: Option<Box<SerializingPage<'a>>>,
|
||||
later_updated: Option<Box<SerializingPage<'a>>>,
|
||||
earlier: Option<Box<SerializingPage<'a>>>,
|
||||
later: Option<Box<SerializingPage<'a>>>,
|
||||
title_prev: Option<Box<SerializingPage<'a>>>,
|
||||
|
@ -115,6 +117,12 @@ impl<'a> SerializingPage<'a> {
|
|||
let heavier = page
|
||||
.heavier
|
||||
.map(|k| Box::new(Self::from_page_basic(pages.get(k).unwrap(), Some(library))));
|
||||
let earlier_updated = page
|
||||
.earlier_updated
|
||||
.map(|k| Box::new(Self::from_page_basic(pages.get(k).unwrap(), Some(library))));
|
||||
let later_updated = page
|
||||
.later_updated
|
||||
.map(|k| Box::new(Self::from_page_basic(pages.get(k).unwrap(), Some(library))));
|
||||
let earlier = page
|
||||
.earlier
|
||||
.map(|k| Box::new(Self::from_page_basic(pages.get(k).unwrap(), Some(library))));
|
||||
|
@ -161,6 +169,8 @@ impl<'a> SerializingPage<'a> {
|
|||
lang: &page.lang,
|
||||
lighter,
|
||||
heavier,
|
||||
earlier_updated,
|
||||
later_updated,
|
||||
earlier,
|
||||
later,
|
||||
title_prev,
|
||||
|
@ -225,6 +235,8 @@ impl<'a> SerializingPage<'a> {
|
|||
lang: &page.lang,
|
||||
lighter: None,
|
||||
heavier: None,
|
||||
earlier_updated: None,
|
||||
later_updated: None,
|
||||
earlier: None,
|
||||
later: None,
|
||||
title_prev: None,
|
||||
|
|
|
@ -3,13 +3,12 @@ use std::path::{Path, PathBuf};
|
|||
|
||||
use slotmap::{DefaultKey, DenseSlotMap};
|
||||
|
||||
use front_matter::SortBy;
|
||||
|
||||
use crate::content::{Page, Section};
|
||||
use crate::sorting::{
|
||||
find_siblings, sort_pages_by_date, sort_pages_by_title, sort_pages_by_weight,
|
||||
};
|
||||
use config::Config;
|
||||
use front_matter::{PageFrontMatter, SortBy};
|
||||
|
||||
// Like vec! but for HashSet
|
||||
macro_rules! set {
|
||||
|
@ -265,52 +264,47 @@ impl Library {
|
|||
/// Sort all sections pages according to sorting method given
|
||||
/// Pages that cannot be sorted are set to the section.ignored_pages instead
|
||||
pub fn sort_sections_pages(&mut self) {
|
||||
fn get_data<'a, T>(
|
||||
section: &'a Section,
|
||||
pages: &'a DenseSlotMap<DefaultKey, Page>,
|
||||
field: impl Fn(&'a PageFrontMatter) -> Option<T>,
|
||||
) -> Vec<(&'a DefaultKey, Option<T>, &'a str)> {
|
||||
section
|
||||
.pages
|
||||
.iter()
|
||||
.map(|k| {
|
||||
if let Some(page) = pages.get(*k) {
|
||||
(k, field(&page.meta), page.permalink.as_ref())
|
||||
} else {
|
||||
unreachable!("Sorting got an unknown page")
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
let mut updates = HashMap::new();
|
||||
for (key, section) in &self.sections {
|
||||
let (sorted_pages, cannot_be_sorted_pages) = match section.meta.sort_by {
|
||||
SortBy::None => continue,
|
||||
SortBy::Date => {
|
||||
let data = section
|
||||
.pages
|
||||
.iter()
|
||||
.map(|k| {
|
||||
if let Some(page) = self.pages.get(*k) {
|
||||
(k, page.meta.datetime, page.permalink.as_ref())
|
||||
} else {
|
||||
unreachable!("Sorting got an unknown page")
|
||||
let data = get_data(section, &self.pages, |meta| meta.datetime);
|
||||
|
||||
sort_pages_by_date(data)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
SortBy::UpdateDate => {
|
||||
let data = get_data(section, &self.pages, |meta| {
|
||||
std::cmp::max(meta.datetime, meta.updated_datetime)
|
||||
});
|
||||
|
||||
sort_pages_by_date(data)
|
||||
}
|
||||
SortBy::Title => {
|
||||
let data = section
|
||||
.pages
|
||||
.iter()
|
||||
.map(|k| {
|
||||
if let Some(page) = self.pages.get(*k) {
|
||||
(k, page.meta.title.as_deref(), page.permalink.as_ref())
|
||||
} else {
|
||||
unreachable!("Sorting got an unknown page")
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let data = get_data(section, &self.pages, |meta| meta.title.as_deref());
|
||||
|
||||
sort_pages_by_title(data)
|
||||
}
|
||||
SortBy::Weight => {
|
||||
let data = section
|
||||
.pages
|
||||
.iter()
|
||||
.map(|k| {
|
||||
if let Some(page) = self.pages.get(*k) {
|
||||
(k, page.meta.weight, page.permalink.as_ref())
|
||||
} else {
|
||||
unreachable!("Sorting got an unknown page")
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let data = get_data(section, &self.pages, |meta| meta.weight);
|
||||
|
||||
sort_pages_by_weight(data)
|
||||
}
|
||||
|
@ -329,6 +323,10 @@ impl Library {
|
|||
page.earlier = val2;
|
||||
page.later = val1;
|
||||
}
|
||||
SortBy::UpdateDate => {
|
||||
page.earlier_updated = val2;
|
||||
page.later_updated = val1;
|
||||
}
|
||||
SortBy::Title => {
|
||||
page.title_prev = val1;
|
||||
page.title_next = val2;
|
||||
|
|
Loading…
Reference in a new issue