Period Archive Quirk
I am working on a Bootstrap 4 theme. I am working to create the period_archives.html. It generates the subpages in the posts structure just fine. However, in the base period_archives.html page, the {{ period }} jinja2 variable does not work. I have a work around. It is pretty sloppy and it requires the jinja2 extension do. I would prefer to have direct access to the period variable on the base period_archives page so I don't have to code around the issue.
I will say that it has been a while since I have messed with theming in Pelican so I may be approaching the period_archives page incorrectly. If there is a better way to approach this issue or a better work around, i would be happy to have some help. Thanks in advance!
My workaround, assuming you have the jinja2 do extension turned on looks like this:
{% if output_file == 'period_archives.html' %}
{% set period = [] %}
{% for year, date_year in dates|groupby( 'date.year' )|sort(reverse=True) %}
{% do period.append(year) %}
{% endfor %}
{% endif %}
- [x] I have searched the issues (including closed ones) and believe that this is not a duplicate.
- [x] I have searched the documentation and believe that my question is not covered.
I'm a bit confused. What is period_archive.html? The template name is period_archives.html (note the s at the end)
I'm a bit confused. What is
period_archive.html? The template name isperiod_archives.html(note thesat the end)
I missed the trailing s in the page name in my description. Per the code, it is named correctly in the project. I have edited the question to add the s's. Hopefully that eliminated any confusion you are having.
Can you show an example with the issue? I cannot reproduce it with template from default theme (the one I linked earlier). That one uses period variable and produces output as expected.
$ cat pelicanconf.py
MONTH_ARCHIVE_SAVE_AS = 'posts/{date:%Y}/{date:%b}/index.html'
$ pelican content
WARNING: Feeds generated without SITEURL set properly may not be valid
WARNING: No timezone information specified in the settings. Assuming your timezone is UTC for feed generation. Check https://docs.getpelican.com/en/latest/settings.html#TIMEZONE for more information
Done: Processed 2 articles, 0 drafts, 0 pages, 0 hidden pages and 0 draft pages in 0.12 seconds.
$ grep "Archives" output/posts/2020/Jan/index.html
<h1>Archives for January 2020</h1>
I have a solution that works for me. It is far from elegant. When you go to the base page of http://127.0.0.1:8000/period_archives.html you cannot access the period variable. On the sub pages such as http://127.0.0.1:8000/posts/2016/ the period variable is accessible. To make it so that both on the http://127.0.0.1:8000/period_archives.html and http://127.0.0.1:8000/posts/2016/ the period variable works, I have implemented the following code using Bootstrap 4.
{% extends "base.html" %}
{% if output_file == 'period_archives.html' %}
{% set period = [] %}
{% for year in dates|groupby( 'date.year' )|sort(reverse=True) %}
{% do period.append(year[0]) %}
{% endfor %}
{% endif %}
{% block title %}
{{ SITENAME }} - {{ period | reverse | join(', ') }} Period Archives
{% endblock %}
{% block breadcrumbs %}
<ul class="breadcrumb">
<li><a href="{{ SITEURL }}" title="{{ SITENAME }}"><i class="fa fa-home fa-lg"></i></a></li>
<li> / </li>
<li class="active">{{ ('Archives') }}</li>
</ul>
{% endblock %}
{% block content %}
<section id="content">
<h1>Archives for {{ period | join (', ') }} </h1>
<div id="archives">
{% for year, date_year in dates|groupby( 'date.year' )|sort(reverse=True) %}
<h3>
{% if dates | length < 2 %}
<span class="expand_caret fas fa-caret-down"></span> {{ year }}
{% else %}
<a data-toggle="collapse" data-taget="#collapse-{{ year }}" href="#collapse-{{ year }}" aria-expanded="false">
<span class="expand_caret fas fa-caret-down"></span>
</a>
<a href="{{ SITEURL }}/{{ PERIOD_ARCHIVES_URL | default('posts') }}/{{ year }}" class="text">{{ year }}</a>
{% endif %}
</h3>
<ul id="collapse-{{ year }}" {% if dates | length > 1 %} class="collapse" {% endif %}>
{% for article in date_year %}
<li>
<span class="categories-timestamp"><time datetime="{{ article.date.isoformat() }}">{{ article.locale_date }}</time></span>
<a href="{{ SITEURL }}/{{ article.url }}">{{ article.title }}{% if article.subtitle %} - {{ article.subtitle }}{% endif %}</a>
</li>
{% endfor %}
</ul>
{% endfor %}
</div>
</section>
{% endblock %}
It ideally we would be able to access the period variable on http://127.0.0.1:8000/period_archives.html it would save a lot of coding around. But I think I have sorted the issue for my specific instance.
Has there been any thought to including the period variable on the base http://127.0.0.1:8000/period_archives.html?
Where does http://127.0.0.1:8000/period_archives.html come from? That's not a standard output pelican generates.
The same place I generate all of my templates, in the pelicanconf.py. Currently, the line that generates most of my site is:
DIRECT_TEMPLATES = ['index', 'authors', 'categories', 'tags', 'period_archives', 'archives', 'search']
Well, that's not how period_archives works. It is controlled by YEAR_ARCHIVE_*/MONTH_ARCHIVE_*/DAY_ARCHIVE_* and period is set to the specific year/year,month/year,month,day for the output page, i.e. http://127.0.0.1:8000/posts/2016/ one that you say "works" will have period == ['2016']. And collection variables like articles will contain posts from that year/month/day.
DIRECT_TEMPLATES is for generic collection (and related) outputs. It doesn't matter if you put period_archives there. pelican will not have any context for a period to provide, just like it won't make sense having a period in categories. And I'm not even sure what the period variable should contain in that case. You're putting a list of years, but that's specific to your site/theme.
Maybe I am using it wrong. It seemed from the limited instructions, that period_archives was a replacement for the generic archives.
Maybe it should be another page? I am just not sure how to use the period_archives feature without a base page? Sure it creates those indexes but how do you get to them?
Under the current system there is no base page for the period_archives feature. It seems like it should work like categories and tags? Maybe not? It just seemed like you would want a place to get to all of these index pages that the period_archives feature is creating?
If it should work like categories and tags then having the period variable available in period_archives.html would be very helpful. If you are suppose to access this feature another way, some documentation indicating its use would be helpful?
Ah, I think I understand now. You want a way to create an index containing links to all the period archive pages generated. That's reasonable, but it's not actually the period variable currently available in the template. Well, it is related but not only that. You'd need the URLs for these. Would adding a dict with keys as period entries and values as URLs to the global context work? It could be named as period_archives as well. Something like this:
period_archives = {
'year': {
('2016',) : 'http://127.0.0.1:8000/posts/2016/'
# ...
},
'month': {
('2016', 'Jan'): 'http://127.0.0.1:8000/posts/2016/Jan/'
# ...
},
'day': {
# ...
}
}
Entries year, month or day will be available only if you enable corresponding period archive with the YEAR_ARCHIVE_* etc. So if you only define MONTH_ARCHIVE_SAVE_AS, you'll get period_archives = {'month': {...}}.
Yes! Exactly this! This is even better than what I was thinking. I would love for this to exist. How can I help?
@avaris: Any chance you could guide Brian toward a way of implementing this feature so he could help build it?
I had a similar issue while implementing period_archives.html template for my Plumage theme.
I couldn't get the URL to the period page, so I came up with an ugly hack to extract it from the output_file variable. See: https://github.com/kdeldycke/plumage/commit/c7f1580b2ae3a9170674dfd97dfd27c0bf0fbcab#diff-2ce3b08489221265269b19fcd1dad303R9-R12
Ah, I think I understand now. You want a way to create an index containing links to all the period archive pages generated. That's reasonable, but it's not actually the
periodvariable currently available in the template. Well, it is related but not only that. You'd need the URLs for these. Would adding a dict with keys asperiodentries and values as URLs to the global context work? It could be named asperiod_archivesas well. Something like this:period_archives = { 'year': { ('2016',) : 'http://127.0.0.1:8000/posts/2016/' # ... }, 'month': { ('2016', 'Jan'): 'http://127.0.0.1:8000/posts/2016/Jan/' # ... }, 'day': { # ... } }Entries
year,monthordaywill be available only if you enable corresponding period archive with theYEAR_ARCHIVE_*etc. So if you only defineMONTH_ARCHIVE_SAVE_AS, you'll getperiod_archives = {'month': {...}}.
I submitted #3148 for this.
As explained in the PR, the data structure I implemented is as follows:
period_archives = {
'year': [
{
'period': ('2023',),
'period_num': (2023,),
'save_as': 'posts/2023/index.html',
'url': 'posts/2023/',
'articles': [<Article>, ...],
'dates': [<Article>, ...],
},
# ...
],
'month': [
{
'period': ('2023', 'Jun'),
'period_num': (2023, 6),
'save_as': 'posts/2023/06/index.html',
'url': 'posts/2023/06/',
'articles': [<Article>, ...],
'dates': [<Article>, ...],
},
# ...
],
'day': [
# ...
]
}
This should make for more-readable templates, and allows for more index page possibilities (e.g. article counts, actually listing the articles).