feat(series): reference the series in its pages

The reference is configurable from none to link to summary to something completely custom.
This commit is contained in:
ZzMzaw 2024-10-05 07:42:36 +02:00
parent 45705ed9c6
commit e1bdb01b6a
10 changed files with 219 additions and 0 deletions

View file

@ -0,0 +1,20 @@
+++
title = "An introduction to series"
date = 2023-05-21
description = "This first article introduces how does series works and how to configure them."
[taxonomies]
tags = ["showcase", "tutorial"]
[extra]
series_page_introduction = "link"
series_page_introduction_variables = { position = "first", toto = "TOTO!!! "}
+++
{{ admonition(type="warning", icon="warning", title="IMPORTANT", text="This article has been introduced retroactively to showcase series.") }}
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

View file

@ -0,0 +1,19 @@
+++
title = "How to organise a series' pages"
date = 2023-08-29
description = "This second article focuses on how to organisation the pages of a series."
[taxonomies]
tags = ["showcase", "tutorial"]
[extra]
series_page_introduction = "summary"
+++
{{ admonition(type="warning", icon="warning", title="IMPORTANT", text="This article has been introduced retroactively to showcase series.") }}
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

View file

@ -0,0 +1,16 @@
+++
title = "Series cheat sheet"
date = 2024-08-08
description = "This last article provides an overview of series and describe all possible parameters."
[taxonomies]
tags = ["showcase", "tutorial", "FAQ"]
[extra]
series_page_introduction = "custom"
+++
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

View file

@ -0,0 +1,21 @@
+++
title = "How to deal with series"
template = "series.html"
sort_by = "slug"
description = "This series explains how to properly configure a series."
transparent = true
[extra]
series = true
quick_navigation_buttons = true
post_listing_index_reversed = false
series_page_introduction = "none"
+++
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

View file

@ -66,6 +66,7 @@ load_comments = "Load comments"
series = "SERIE"
series_jump_to_posts = "Jump to posts"
series_posts = "Series' posts:"
series_page_headline = "This article is part of the series: $SERIES_HTML_LINK."
# Copy code block button.
copied = "Copied!"

View file

@ -66,6 +66,7 @@ load_comments = "Afficher les commentaires"
series = "SERIE"
series_jump_to_posts = "Aller aux articles"
series_posts = "Articles de la série :"
series_page_headline = "Cet article fait partie de la série : $SERIES_HTML_LINK."
# Copy code block button.
copied = "Copié !"

View file

@ -267,3 +267,28 @@ details summary {
[data-force-text-direction="rtl"] * {
direction: inherit;
}
.series-page-introduction {
margin-top: 1rem;
margin-bottom: 1rem;
border: 1px solid var(--primary-color);
border-left-width: 0.3rem;
border-radius: 10px;
padding: 1rem;
p {
margin: 0;
}
summary::marker {
color: var(--primary-color);
font-size: 1.3rem;
}
details {
ol {
margin-top: 0;
margin-bottom: 0;
}
}
}

View file

@ -5,6 +5,7 @@
{% import "macros/settings.html" as macros_settings %}
{% import "macros/table_of_contents.html" as macros_toc %}
{% import "macros/translate.html" as macros_translate %}
{% import "macros/series_page.html" as macros_series_page %}
{# Load the internationalisation data for the current language from
the .toml files in the user's '/i18n' folder, falling back to the theme's.

View file

@ -0,0 +1,84 @@
{#
Those macros deal with introduction and navigation for series pages.
Using macros have been prefered over partial inclusion or inline code to make sure series_ordered_pages is forced to be used.
A section's pages natural order is invalid in case of reversed pagination which would lead to invalid series' pages order.
To prevent this, pages are ordered correctly in a separate variable which must be used instead of the series section pages.
#}
{#
Computes the introduction of a series's page.
Parameters:
- `page`: The page object being part of the series.
- `series_section`: The series' section the page belongs to.
- `series_ordered_pages`: The series' pages properly ordered (see at the top of this file for an explanation).
- `language_strings`: A dictionary containing the translation strings.
#}
{% macro get_introduction(page, series_section, series_ordered_pages, language_strings) %}
{%- if "series" in series_section.extra and series_section.extra.series -%}
{%- set allowed_series_page_introduction = ["none", "link", "summary", "custom"] -%}
{%- set series_page_introduction = macros_settings::evaluate_setting_priority(setting="series_page_introduction", page=page, section=series_section, default_global_value="link") -%}
{%- if series_page_introduction not in allowed_series_page_introduction -%}
{{ throw(message="ERROR: Invalid value for series_page_description. Allowed values are 'none', 'link', 'summary' or 'custom' (defaults to 'link').") }}
{%- endif -%}
{# Prepare variables for substitution #}
{%- set series_title = series_section.title -%}
{%- set series_permalink = series_section.permalink -%}
{%- set series_html_link = '<a href="' ~ series_section.permalink ~ '" aria_label="' ~ series_section.title ~ '">' ~ series_section.title ~ '</a>' -%}
{%- set series_pages_list = [] -%}
{%- set series_pages_number = 0 -%}
{%- set series_page_index = 0 -%}
{%- for series_page in series_ordered_pages -%}
{%- set_global series_pages_number = series_pages_number + 1 -%}
{%- if series_page.relative_path == page.relative_path -%}
{%- set_global series_page_index = series_pages_number -%}
{%- set series_pages_list_item = '<li>' ~ series_page.title ~ '</li>' -%}
{%- else -%}
{%- set series_pages_list_item = '<li><a href="' ~ series_page.permalink ~ '" aria_label="' ~ series_page.title ~ '">' ~ series_page.title ~ '</a></li>' -%}
{%- endif -%}
{%- set_global series_pages_list = series_pages_list | concat(with=series_pages_list_item) -%}
{%- endfor -%}
{%- set series_pages_number = series_pages_number | as_str -%}
{%- set series_page_index = series_page_index | as_str -%}
{%- set series_pages_list = series_pages_list | join(sep="") -%}
{%- if macros_settings::evaluate_setting_priority(setting="post_listing_index_reversed", page=series_section, default_global_value=false) == "true" -%}
{%- set series_pages_ordered_list = '<ol reversed>' ~ series_pages_list ~ '</ol>' -%}
{%- else -%}
{%- set series_pages_ordered_list = '<ol>' ~ series_pages_list ~ '</ol>' -%}
{%- endif -%}
{%- set series_pages_unordered_list = '<ul>' ~ series_pages_list ~ '</ul>' -%}
{# Define headline #}
{%- set series_page_headline = macros_translate::translate(key="series_page_headline", default="This article is part of the series: $SERIES_HTML_LINK", language_strings=language_strings) -%}
{%- set series_page_headline = series_section.extra.series_page_headline | default(value=series_page_headline) -%}
{%- set series_page_headline = series_page_headline | replace(from="$SERIES_TITLE", to=series_title) | replace(from="$SERIES_PERMALINK", to=series_permalink) | replace(from="$SERIES_HTML_LINK", to=series_html_link) -%}
{%- set series_page_headline = series_page_headline | replace(from="$SERIES_PAGES_NUMBER", to=series_pages_number) | replace(from="$SERIES_PAGE_INDEX", to=series_page_index) | replace(from="$SERIES_PAGES_OLIST", to=series_pages_ordered_list) | replace(from="$SERIES_PAGES_ULIST", to=series_pages_unordered_list) -%}
{# Define description #}
{%- set series_page_description = series_section.extra.series_page_description | default(value=series_section.description) -%}
{%- set series_page_description = series_page_description | replace(from="$SERIES_TITLE", to=series_title) | replace(from="$SERIES_PERMALINK", to=series_permalink) | replace(from="$SERIES_HTML_LINK", to=series_html_link) -%}
{%- set series_page_description = series_page_description | replace(from="$SERIES_PAGES_NUMBER", to=series_pages_number) | replace(from="$SERIES_PAGE_INDEX", to=series_page_index) | replace(from="$SERIES_PAGES_OLIST", to=series_pages_ordered_list) | replace(from="$SERIES_PAGES_ULIST", to=series_pages_unordered_list) -%}
{%- if series_page_introduction == "link" -%}
<section class="series-page-introduction">
<p>{{ series_page_headline | safe }}</p>
</section>
{%- elif series_page_introduction == "summary" -%}
<section class="series-page-introduction">
<details>
<summary>{{ series_page_headline | safe }}</summary>
{{ series_page_description | safe }}
<nav>
{{ series_pages_ordered_list | safe }}
</nav>
</details>
</section>
{%- elif series_page_introduction == "custom" -%}
<section class="series-page-introduction-custom">
{{ series_page_description | safe }}
</section>
{%- endif -%}
{%- endif -%}
{% endmacro %}

View file

@ -180,6 +180,37 @@ Current section extra: {% if current_section %}{{ current_section.extra | json_e
{% endif %}
</ul>
{# A page is part of a series if one of the sections above (whether it is transparent or not) has the `extra.series` parameter set to true. #}
{# As a series might be a transparent section in order to mix up its articles with those of the section just above or the root, #}
{# there is no other way but to compute the potential path of each ancestor section related to the page and look for the first one being a series. #}
{# Using the `ancestors` field of a section is not possible because transparent sections are not present in this field. #}
{%- set current_path = [] -%}
{%- set section_paths = [] -%}
{%- for path in page.relative_path | split(pat="/") | slice(end=-1) -%}
{%- set_global current_path = current_path | concat(with=path) -%}
{%- set section_path = current_path | concat(with="_index.md") | join(sep="/") -%}
{%- set_global section_paths = section_paths | concat(with=section_path) -%}
{%- endfor -%}
{# The series the page is part of is the closest section flagged as a series, if any #}
{%- for section_path in section_paths | reverse -%}
{%- set section_file_exists = load_data(path=section_path, required=false) -%}
{%- if section_file_exists -%}
{%- set loaded_section = get_section(path=section_path,lang=lang) -%}
{%- if "series" in loaded_section.extra and loaded_section.extra.series -%}
{%- set_global series_section = loaded_section -%}
{%- set_global series_ordered_pages = loaded_section.pages -%}
{%- if loaded_section.paginated and loaded_section.paginate_reversed -%}
{%- set_global series_ordered_pages = loaded_section.pages | reverse -%}
{%- endif -%}
{%- break -%}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
{% if series_section %}
{{ macros_series_page::get_introduction(page=page, series_section=series_section, series_ordered_pages=series_ordered_pages, language_strings=language_strings)}}
{% endif %}
{% if page.extra.tldr %}
<div class="admonition note">
<div class="admonition-icon admonition-icon-note"></div>