WIP: add an 'updated' field to pages

Also change a few other things to use it, as noted in CHANGELOG.md.

TODO:

- Write a couple of tests: updated field, last_updated template variable

One slight open questions: should `updated` default to the value of
`date` rather than to None? Then pages with `date` could safely assume
`updated`.
This commit is contained in:
Chris Morgan 2019-10-08 01:39:33 +11:00
parent 0cc1435f35
commit eb7751955a
12 changed files with 41 additions and 16 deletions

View file

@ -8,10 +8,15 @@
- Config value `rss_limit` is renamed to `feed_limit` - Config value `rss_limit` is renamed to `feed_limit`
- Config value `languages.*.rss` is renamed to `languages.*.feed` - Config value `languages.*.rss` is renamed to `languages.*.feed`
- Config value `generate_rss` is renamed to `generate_feed` - Config value `generate_rss` is renamed to `generate_feed`
- Feed template variable `last_build_date` is renamed to `latest_date`
Users with existing feeds should either set `feed_filename = "rss.xml"` in config.toml to keep things the same, or set up a 3xx redirect from rss.xml to atom.xml so that existing feed consumers arent broken. Users with existing feeds should either set `feed_filename = "rss.xml"` in config.toml to keep things the same, or set up a 3xx redirect from rss.xml to atom.xml so that existing feed consumers arent broken.
- The feed template variable `last_build_date` is renamed to `last_updated` to more accurately reflect its semantics
- The sitemap templates `SitemapEntry` types `date` field has been renamed to `updated` to reflect that it will use the `updated` front-matter field if available, rather than `date`
### Other
- Add `updated` front-matter field for pages, which sitemap templates will use for the `SitemapEntry.date` field instead of the `date` front-matter field, and which the default Atom feed template will use
## 0.10.2 (unreleased) ## 0.10.2 (unreleased)
- Fix link checker not looking for anchor with capital id/name - Fix link checker not looking for anchor with capital id/name

View file

@ -16,6 +16,9 @@ pub struct PageFrontMatter {
pub title: Option<String>, pub title: Option<String>,
/// Description in <meta> that appears when linked, e.g. on twitter /// Description in <meta> that appears when linked, e.g. on twitter
pub description: Option<String>, pub description: Option<String>,
/// Updated date
#[serde(default, deserialize_with = "from_toml_datetime")]
pub updated: Option<String>,
/// Date if we want to order pages (ie blog post) /// Date if we want to order pages (ie blog post)
#[serde(default, deserialize_with = "from_toml_datetime")] #[serde(default, deserialize_with = "from_toml_datetime")]
pub date: Option<String>, pub date: Option<String>,
@ -117,6 +120,7 @@ impl Default for PageFrontMatter {
PageFrontMatter { PageFrontMatter {
title: None, title: None,
description: None, description: None,
updated: None,
date: None, date: None,
datetime: None, datetime: None,
datetime_tuple: None, datetime_tuple: None,

View file

@ -63,6 +63,7 @@ pub struct SerializingPage<'a> {
ancestors: Vec<String>, ancestors: Vec<String>,
title: &'a Option<String>, title: &'a Option<String>,
description: &'a Option<String>, description: &'a Option<String>,
updated: &'a Option<String>,
date: &'a Option<String>, date: &'a Option<String>,
year: Option<i32>, year: Option<i32>,
month: Option<u32>, month: Option<u32>,
@ -126,6 +127,7 @@ impl<'a> SerializingPage<'a> {
title: &page.meta.title, title: &page.meta.title,
description: &page.meta.description, description: &page.meta.description,
extra: &page.meta.extra, extra: &page.meta.extra,
updated: &page.meta.updated,
date: &page.meta.date, date: &page.meta.date,
year, year,
month, month,
@ -182,6 +184,7 @@ impl<'a> SerializingPage<'a> {
title: &page.meta.title, title: &page.meta.title,
description: &page.meta.description, description: &page.meta.description,
extra: &page.meta.extra, extra: &page.meta.extra,
updated: &page.meta.updated,
date: &page.meta.date, date: &page.meta.date,
year, year,
month, month,

View file

@ -1065,7 +1065,14 @@ impl Site {
pages.par_sort_unstable_by(sort_actual_pages_by_date); pages.par_sort_unstable_by(sort_actual_pages_by_date);
context.insert("latest_date", &pages[0].meta.date.clone()); context.insert(
"last_updated",
pages.iter()
.filter_map(|page| page.meta.updated.as_ref())
.chain(pages[0].meta.date.as_ref())
.max() // I love lexicographically sorted date strings
.unwrap(), // Guaranteed because of pages[0].meta.date
);
let library = self.library.read().unwrap(); let library = self.library.read().unwrap();
// limit to the last n elements if the limit is set; otherwise use all. // limit to the last n elements if the limit is set; otherwise use all.
let num_entries = self.config.feed_limit.unwrap_or_else(|| pages.len()); let num_entries = self.config.feed_limit.unwrap_or_else(|| pages.len());

View file

@ -14,7 +14,7 @@ use tera::{Map, Value};
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct SitemapEntry<'a> { pub struct SitemapEntry<'a> {
pub permalink: Cow<'a, str>, pub permalink: Cow<'a, str>,
pub date: Option<String>, pub updated: Option<String>,
pub extra: Option<&'a Map<String, Value>>, pub extra: Option<&'a Map<String, Value>>,
} }
@ -33,8 +33,8 @@ impl<'a> PartialEq for SitemapEntry<'a> {
impl<'a> Eq for SitemapEntry<'a> {} impl<'a> Eq for SitemapEntry<'a> {}
impl<'a> SitemapEntry<'a> { impl<'a> SitemapEntry<'a> {
pub fn new(permalink: Cow<'a, str>, date: Option<String>) -> Self { pub fn new(permalink: Cow<'a, str>, updated: Option<String>) -> Self {
SitemapEntry { permalink, date, extra: None } SitemapEntry { permalink, updated, extra: None }
} }
pub fn add_extra(&mut self, extra: &'a Map<String, Value>) { pub fn add_extra(&mut self, extra: &'a Map<String, Value>) {
@ -65,11 +65,10 @@ pub fn find_entries<'a>(
.pages_values() .pages_values()
.iter() .iter()
.map(|p| { .map(|p| {
let date = match p.meta.date { let mut entry = SitemapEntry::new(
Some(ref d) => Some(d.to_string()), Cow::Borrowed(&p.permalink),
None => None, p.meta.updated.clone().or_else(|| p.meta.date.clone()),
}; );
let mut entry = SitemapEntry::new(Cow::Borrowed(&p.permalink), date);
entry.add_extra(&p.meta.extra); entry.add_extra(&p.meta.extra);
entry entry
}) })

View file

@ -7,7 +7,7 @@
<link href="{{ feed_url | safe }}" rel="self" type="application/atom+xml"/> <link href="{{ feed_url | safe }}" rel="self" type="application/atom+xml"/>
<link href="{{ config.base_url | safe }}"/> <link href="{{ config.base_url | safe }}"/>
<generator uri="https://www.getzola.org/">Zola</generator> <generator uri="https://www.getzola.org/">Zola</generator>
<updated>{{ latest_date | date(format="%+") }}</updated> <updated>{{ last_updated | date(format="%+") }}</updated>
<id>{{ feed_url | safe }}</id> <id>{{ feed_url | safe }}</id>
{%- for page in pages %} {%- for page in pages %}
<entry <entry
@ -15,6 +15,7 @@
> >
<title>{{ page.title }}</title> <title>{{ page.title }}</title>
<published>{{ page.date | date(format="%+") }}</published> <published>{{ page.date | date(format="%+") }}</published>
<updated>{{ page.updated | default(value=page.date) | date(format="%+") }}</updated>
<link href="{{ page.permalink | safe }}" type="text/html"/> <link href="{{ page.permalink | safe }}" type="text/html"/>
<id>{{ page.permalink | safe }}</id> <id>{{ page.permalink | safe }}</id>
<content type="html">{{ page.content }}</description> <content type="html">{{ page.content }}</description>

View file

@ -7,7 +7,7 @@
<generator>Zola</generator> <generator>Zola</generator>
<language>{{ config.default_language }}</language> <language>{{ config.default_language }}</language>
<atom:link href="{{ feed_url | safe }}" rel="self" type="application/rss+xml"/> <atom:link href="{{ feed_url | safe }}" rel="self" type="application/rss+xml"/>
<lastBuildDate>{{ latest_date | date(format="%a, %d %b %Y %H:%M:%S %z") }}</lastBuildDate> <lastBuildDate>{{ last_updated | date(format="%a, %d %b %Y %H:%M:%S %z") }}</lastBuildDate>
{%- for page in pages %} {%- for page in pages %}
<item> <item>
<title>{{ page.title }}</title> <title>{{ page.title }}</title>

View file

@ -3,8 +3,8 @@
{%- for sitemap_entry in entries %} {%- for sitemap_entry in entries %}
<url> <url>
<loc>{{ sitemap_entry.permalink | escape_xml | safe }}</loc> <loc>{{ sitemap_entry.permalink | escape_xml | safe }}</loc>
{%- if sitemap_entry.date %} {%- if sitemap_entry.updated %}
<lastmod>{{ sitemap_entry.date }}</lastmod> <lastmod>{{ sitemap_entry.updated }}</lastmod>
{%- endif %} {%- endif %}
</url> </url>
{%- endfor %} {%- endfor %}

View file

@ -93,6 +93,10 @@ description = ""
# Setting this overrides a date set in the filename. # Setting this overrides a date set in the filename.
date = date =
# The last updated date of the post, if different from the date.
# Same format as `date`.
updated =
# The weight as defined on the Section page of the documentation. # The weight as defined on the Section page of the documentation.
# If the section variable `sort_by` is set to `weight`, then any page that lacks a `weight` # If the section variable `sort_by` is set to `weight`, then any page that lacks a `weight`
# will not be rendered. # will not be rendered.

View file

@ -20,6 +20,6 @@ need to provide a template yourself.
The feed template gets three variables in addition to `config`: The feed template gets three variables in addition to `config`:
- `feed_url`: the full url to that specific feed - `feed_url`: the full url to that specific feed
- `latest_date`: the date of the latest post - `last_updated`: the most recent `updated` or `date` field of any post
- `pages`: see [page variables](@/documentation/templates/pages-sections.md#page-variables) for - `pages`: see [page variables](@/documentation/templates/pages-sections.md#page-variables) for
a detailed description of what this contains a detailed description of what this contains

View file

@ -19,6 +19,8 @@ content: String;
title: String?; title: String?;
description: String?; description: String?;
date: String?; date: String?;
// `updated` will be the same as `date` if `date` is specified but `updated` is not in front-matter
updated: String?;
slug: String; slug: String;
path: String; path: String;
draft: Bool; draft: Bool;

View file

@ -25,7 +25,7 @@ A `SitemapEntry` has the following fields:
```ts ```ts
permalink: String; permalink: String;
date: String?; updated: String?;
extra: Hashmap<String, Any>?; extra: Hashmap<String, Any>?;
``` ```