mirror of
https://github.com/welpo/tabi.git
synced 2025-10-10 23:38:53 +02:00
- Add templating for outro, similar/extended from intro code
- Renames series_page_introduction_placeholders to series_template_placeholders - Removes `post_listing_index_reversed` in favour of outro templates - Docs!
This commit is contained in:
parent
c056b53d26
commit
434769376e
11 changed files with 461 additions and 172 deletions
|
@ -165,7 +165,7 @@ post_listing_date = "date"
|
|||
# Determines if indexes should be increasing (false) or decreasing (true) in series' posts list.
|
||||
# It has only effect if the section uses indexes metadata (which is only the case for series as of now).
|
||||
# Can be set at section levels, following the hierarchy: section > config. See: https://welpo.github.io/tabi/blog/mastering-tabi-settings/#settings-hierarchy
|
||||
post_listing_index_reversed = false # Defaults to false.
|
||||
post_listing_index_reversed = false # Defaults to false.
|
||||
|
||||
# DEPRECATED!
|
||||
# Use Zola's built-in `bottom_footnotes = true` in the [markdown] section instead. (Available since v0.19.0)
|
||||
|
@ -191,10 +191,6 @@ serve_local_mermaid = true
|
|||
# Can be set at page or section levels, following the hierarchy: page > section > config. See: https://welpo.github.io/tabi/blog/mastering-tabi-settings/#settings-hierarchy
|
||||
show_previous_next_article_links = false
|
||||
|
||||
# Show links to previous and next series articles at the bottom of posts which is part of a series.
|
||||
# Can be set at page or section levels, following the hierarchy: page > section > config. See: https://welpo.github.io/tabi/blog/mastering-tabi-settings/#settings-hierarchy
|
||||
show_previous_next_series_article_links = false
|
||||
|
||||
# Invert order of the links to previous and next articles at the bottom of posts.
|
||||
# By default, next articles are on the left side of the page and previous articles are on the right side.
|
||||
# To reverse the order (next articles on the right and previous articles on the left), set it to true.
|
||||
|
|
|
@ -8,5 +8,4 @@ insert_anchor_links = "left"
|
|||
[extra]
|
||||
social_media_card = "blog/social_cards/ca_blog.jpg"
|
||||
show_previous_next_article_links = true
|
||||
show_previous_next_series_article_links = true
|
||||
+++
|
||||
|
|
|
@ -8,5 +8,4 @@ insert_anchor_links = "left"
|
|||
[extra]
|
||||
social_media_card = "blog/social_cards/es_blog.jpg"
|
||||
show_previous_next_article_links = true
|
||||
show_previous_next_series_article_links = true
|
||||
+++
|
||||
|
|
|
@ -8,5 +8,4 @@ insert_anchor_links = "left"
|
|||
[extra]
|
||||
social_media_card = "blog/social_cards/blog.jpg"
|
||||
show_previous_next_article_links = true
|
||||
show_previous_next_series_article_links = true
|
||||
+++
|
||||
|
|
|
@ -7,13 +7,15 @@ description = "This first article introduces how does series works and how to co
|
|||
tags = ["showcase", "tutorial"]
|
||||
|
||||
[extra]
|
||||
series_page_introduction_variables = { position = "first", foo = "FOO!!!"}
|
||||
series_template_variables = { position = "first", foo = "FOO!!!"}
|
||||
|
||||
+++
|
||||
|
||||
{{ 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.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. [^1]
|
||||
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.
|
||||
|
||||
[^1]: Lorem.
|
||||
|
|
|
@ -7,7 +7,9 @@ description = "This second article focuses on how to organisation the pages of a
|
|||
tags = ["showcase", "tutorial"]
|
||||
|
||||
[extra]
|
||||
series_page_introduction_variables = { position = "second", foo = "FOO FOO!!!"}
|
||||
[extra.series_template_variables]
|
||||
position = "second"
|
||||
foo = "FOO FOO!!!"
|
||||
|
||||
+++
|
||||
|
||||
|
|
|
@ -7,14 +7,265 @@ description = "This last article provides an overview of series and describe all
|
|||
tags = ["showcase", "tutorial", "FAQ"]
|
||||
|
||||
[extra]
|
||||
series_page_introduction_variables = { position = "third", foo = "FOO FOO FOO!!!"}
|
||||
series_template_variables = { position = "third", foo = "FOO FOO FOO!!!"}
|
||||
toc = true
|
||||
|
||||
+++
|
||||
|
||||
## Jump to Posts Feature
|
||||
## Quick Start
|
||||
|
||||
1. Create a directory for your series.
|
||||
2. Create `_index.md` in the series directory.
|
||||
3. Set up the `_index.md` front matter:
|
||||
|
||||
```toml
|
||||
title = "Learning Rust"
|
||||
template = "series.html"
|
||||
sort_by = "slug"
|
||||
transparent = true
|
||||
|
||||
[extra]
|
||||
series = true
|
||||
```
|
||||
|
||||
4. Create your series articles in this directory.
|
||||
|
||||
Want more? Keep reading!
|
||||
|
||||
## Jump to Posts
|
||||
|
||||
When a series has a description over 2000 characters, a "Jump to posts" link automatically appears next to the series title:
|
||||
|
||||
##### TODO: Add screenshot with final design
|
||||
|
||||
To force the feature on or off, use the `show_jump_to_posts` option in the `[extra]` section of your section (series) or in `config.toml`. This setting follows [the hierarchy](@blog/mastering-tabi-settings/index.md#settings-hierarchy).
|
||||
|
||||
## Intro and Outro Templates
|
||||
|
||||
Series articles can have automatic introduction and conclusion sections. These are configured in your series' `_index.md`:
|
||||
|
||||
```toml
|
||||
[extra.series_intro_templates]
|
||||
default = "This article is part of the $SERIES_HTML_LINK series."
|
||||
|
||||
[extra.series_outro_templates]
|
||||
default = "Thanks for reading part $SERIES_PAGE_INDEX of $SERIES_HTML_LINK!"
|
||||
```
|
||||
|
||||
### Placement in Content
|
||||
|
||||
By default:
|
||||
|
||||
- Series introductions appear at the start of your article
|
||||
- Series outro appears at the end (before footnotes, if any)
|
||||
|
||||
You can control exactly where these appear using `<!-- series_intro -->` and `<!-- series_outro -->` in your Markdown:
|
||||
|
||||
```markdown
|
||||
This paragraph appears before the series introduction.
|
||||
|
||||
<!-- series_intro -->
|
||||
|
||||
Main content of the article.
|
||||
|
||||
<!-- series_outro -->
|
||||
|
||||
## Learning Resources
|
||||
|
||||
Extra content…
|
||||
|
||||
[^1]: Footnotes will always appear at the end.
|
||||
```
|
||||
|
||||
## Variables
|
||||
|
||||
Series templates use a flexible variable system that lets you:
|
||||
|
||||
1. Reference series information (title, links)
|
||||
2. Add navigation between articles
|
||||
3. Show progress indicators
|
||||
4. Include custom information using your own variables
|
||||
|
||||
Variables are placeholders starting with `$` that get replaced with actual content when your site builds. For example, `$SERIES_HTML_LINK` becomes a clickable link to your series index page.
|
||||
|
||||
There are three types of variables:
|
||||
|
||||
- [**Basic Series Variables**](#basic-series-variables): General information about the series
|
||||
- [**Navigation Variables**](#navigation-variables): Links to previous/next articles
|
||||
- [**Custom Variables**](#custom-variables): Your own placeholders for additional information
|
||||
|
||||
### Basic Series Variables
|
||||
|
||||
{% wide_container() %}
|
||||
|
||||
| Variable | Availability | Returns | Description | Example Usage | Example Output |
|
||||
|----------|-------------|---------|-------------|---------------|----------------|
|
||||
| `$SERIES_TITLE` | Always | Text | Plain text title of the series | `Part of $SERIES_TITLE` | Part of Learn Rust |
|
||||
| `$SERIES_PERMALINK` | Always | Text | URL to series index | `[See all posts]($SERIES_PERMALINK)` | [See all posts](/series/learn-rust) |
|
||||
| `$SERIES_HTML_LINK` | Always | HTML | Ready-to-use link to series | `Welcome to $SERIES_HTML_LINK!` | Welcome to <a href="/series/learn-rust">Learn Rust</a>! |
|
||||
| `$SERIES_PAGES_NUMBER` | Always | Number | Total articles in series | `A $SERIES_PAGES_NUMBER part series` | A 5 part series |
|
||||
| `$SERIES_PAGE_INDEX` | Always | Number | Current article's position | `Part $SERIES_PAGE_INDEX of $SERIES_PAGES_NUMBER` | Part 3 of 5 |
|
||||
| `$SERIES_PAGES_OLIST` | Always | HTML | Ordered list of all articles | `Articles in series: $SERIES_PAGES_OLIST` | Articles in series: <ol><li>Current article</li><li><a href="...">Other articles</a></li></ol> |
|
||||
| `$SERIES_PAGES_ULIST` | Always | HTML | Unordered list of all articles | `Articles in series: $SERIES_PAGES_ULIST` | Articles in series: <ul><li>Current article</li><li><a href="...">Other articles</a></li></ul> |
|
||||
|
||||
{% end %}
|
||||
|
||||
### Navigation Variables
|
||||
|
||||
{% wide_container() %}
|
||||
|
||||
| Variable | Availability | Returns | Description | Example Usage | Example Output |
|
||||
|----------|-------------|---------|-------------|---------------|----------------|
|
||||
| `$PREV_TITLE` | Previous exists | Text | Previous article's title | `Previously: $PREV_TITLE` | Previously: Setting Up Your Environment |
|
||||
| `$PREV_PERMALINK` | Previous exists | Text | URL to previous article | `[← Back]($PREV_PERMALINK)` | [← Back](/series/learn-rust/setup) |
|
||||
| `$PREV_HTML_LINK` | Previous exists | HTML | Ready-to-use link to previous | `Read $PREV_HTML_LINK first` | Read <a href="/series/learn-rust/setup">Setting Up Your Environment</a> first |
|
||||
| `$PREV_DESCRIPTION` | Previous exists | Text | Description of previous article | `Recap: $PREV_DESCRIPTION` | Recap: Setting up Rust |
|
||||
| `$NEXT_TITLE` | Next exists | Text | Next article's title | `Next up: $NEXT_TITLE` | Next up: Advanced Patterns |
|
||||
| `$NEXT_PERMALINK` | Next exists | Text | URL to next article | `[Continue →]($NEXT_PERMALINK)` | [Continue →](/series/learn-rust/patterns) |
|
||||
| `$NEXT_HTML_LINK` | Next exists | HTML | Ready-to-use link to next | `Continue with $NEXT_HTML_LINK` | Continue with <a href="/series/learn-rust/patterns">Advanced Patterns</a> |
|
||||
| `$NEXT_DESCRIPTION` | Next exists | Text | Description of next article | `Coming up: $NEXT_DESCRIPTION` | Coming up: Learn about Rust's advanced pattern matching features |
|
||||
|
||||
{% end %}
|
||||
|
||||
### First Article Reference
|
||||
|
||||
{% wide_container() %}
|
||||
| Variable | Availability | Returns | Description | Example Usage | Example Output |
|
||||
|----------|-------------|---------|-------------|---------------|----------------|
|
||||
| `$FIRST_TITLE` | Always | Text | First article's title | `Start with $FIRST_TITLE` | Start with Introduction to Rust |
|
||||
| `$FIRST_HTML_LINK` | Always | HTML | Ready-to-use link to first article | `Begin at $FIRST_HTML_LINK` | Begin at <a href="/series/learn-rust/intro">Introduction to Rust</a> |
|
||||
{% end %}
|
||||
|
||||
### Template Example
|
||||
|
||||
{{ admonition(type="tip", title="HTML vs text variables", text="Use HTML variables (ending in `_HTML_LINK`) when you want ready-made links. Use text variables (ending in `_TITLE` or `_PERMALINK`) when you want more control over the formatting.") }}
|
||||
|
||||
```toml
|
||||
# Introduction.
|
||||
[extra.series_intro_templates]
|
||||
next_only = """
|
||||
Welcome to $SERIES_HTML_LINK! This $SERIES_PAGES_NUMBER-part series will teach you Rust from scratch.
|
||||
|
||||
Up next: $NEXT_HTML_LINK - $NEXT_DESCRIPTION
|
||||
"""
|
||||
|
||||
middle = """
|
||||
📚 Part $SERIES_PAGE_INDEX of $SERIES_PAGES_NUMBER in $SERIES_HTML_LINK
|
||||
|
||||
Previously: $PREV_HTML_LINK
|
||||
Next up: $NEXT_HTML_LINK
|
||||
"""
|
||||
|
||||
prev_only = """
|
||||
Welcome to the final part of $SERIES_HTML_LINK!
|
||||
New here? Start with $FIRST_HTML_LINK to build a strong foundation.
|
||||
|
||||
Previously: $PREV_HTML_LINK
|
||||
"""
|
||||
|
||||
# Fallback template.
|
||||
default = "This article is part of the $SERIES_HTML_LINK series."
|
||||
|
||||
|
||||
# Outro.
|
||||
[extra.series_outro_templates]
|
||||
next_only = """
|
||||
Thanks for reading! 🙌
|
||||
|
||||
Continue your journey with $NEXT_HTML_LINK, where $NEXT_DESCRIPTION
|
||||
Or check out the complete [$SERIES_TITLE]($SERIES_PERMALINK) series outline.
|
||||
"""
|
||||
|
||||
middle = """
|
||||
---
|
||||
📝 Series Navigation
|
||||
|
||||
- Previous: $PREV_HTML_LINK
|
||||
- Next: $NEXT_HTML_LINK
|
||||
- [Series Overview]($SERIES_PERMALINK)
|
||||
"""
|
||||
|
||||
prev_only = """
|
||||
🎉 Congratulations! You've completed $SERIES_HTML_LINK.
|
||||
|
||||
Want to review? Here's where we started: $FIRST_HTML_LINK
|
||||
Or check what we just covered in $PREV_HTML_LINK.
|
||||
"""
|
||||
|
||||
# Fallback.
|
||||
default = """
|
||||
---
|
||||
This article is part $SERIES_PAGE_INDEX of $SERIES_PAGES_NUMBER in $SERIES_HTML_LINK.
|
||||
"""
|
||||
```
|
||||
|
||||
### Custom Variables
|
||||
|
||||
Series templates support custom variables for additional information you want to include across your series. The process takes two steps:
|
||||
|
||||
1. Define your placeholders once in the series configuration with `series_template_placeholders`.
|
||||
2. Provide their values in each article with `series_template_variables` (note the different name).
|
||||
|
||||
3. First, define your **placeholders** in your series configuration (`_index.md`):
|
||||
|
||||
```toml
|
||||
[extra]
|
||||
series = true
|
||||
series_template_placeholders = ["$POSITION", "$TOPIC", "$DIFFICULTY"]
|
||||
```
|
||||
|
||||
2. Then, in each series article, provide the values for these placeholders in `series_template_variables`:
|
||||
|
||||
```toml
|
||||
[extra.series_template_variables]
|
||||
position = "first"
|
||||
topic = "Variables and Types"
|
||||
difficulty = "Beginner"
|
||||
```
|
||||
|
||||
### Using Custom Variables
|
||||
|
||||
You can use your custom variables in any template, alongside the built-in variables:
|
||||
|
||||
```toml
|
||||
[extra.series_intro_templates]
|
||||
default = """
|
||||
This is the $POSITION article in $SERIES_HTML_LINK.
|
||||
Today's topic: $TOPIC
|
||||
Difficulty level: $DIFFICULTY
|
||||
"""
|
||||
```
|
||||
|
||||
{{ admonition(type="warning", text="While placeholders are defined with uppercase (`$POSITION`), the variable names in `series_template_variables` must be lowercase (`position`).") }}
|
||||
|
||||
### Example with Custom Variables
|
||||
|
||||
Here's a complete example showing how to use custom variables in a series:
|
||||
|
||||
```toml
|
||||
# In series _index.md
|
||||
[extra]
|
||||
series = true
|
||||
series_template_placeholders = ["$LEARNING_TIME", "$KEY_CONCEPTS"]
|
||||
|
||||
series_intro_templates.default = """
|
||||
📚 Part $SERIES_PAGE_INDEX of $SERIES_PAGES_NUMBER
|
||||
⏱️ Estimated time: $LEARNING_TIME
|
||||
🔑 Key concepts: $KEY_CONCEPTS
|
||||
"""
|
||||
|
||||
# In an article of the series
|
||||
[extra.series_template_variables]
|
||||
learning_time = "30 minutes"
|
||||
key_concepts = "Functions, Error Handling, Pattern Matching"
|
||||
```
|
||||
|
||||
This will output:
|
||||
|
||||
```text
|
||||
📚 Part 2 of 5
|
||||
⏱️ Estimated time: 30 minutes
|
||||
🔑 Key concepts: Functions, Error Handling, Pattern Matching
|
||||
```
|
||||
|
||||
{{ admonition(type="warning", title="Missing Variables", text="If you use a placeholder in your templates but don't provide its value in `series_template_variables`, the build will fail with an error listing the missing variables.") }}
|
||||
|
|
|
@ -13,7 +13,7 @@ quick_navigation_buttons = true
|
|||
show_jump_to_posts = true
|
||||
post_listing_index_reversed = false
|
||||
|
||||
series_page_introduction_placeholders = ["$POSITION", "$FOO", "$BAR"]
|
||||
series_template_placeholders = ["$POSITION", "$FOO", "$BAR"]
|
||||
series_page_introduction = """
|
||||
You can put whatever you want in a custom description.
|
||||
|
||||
|
@ -21,7 +21,20 @@ You can put whatever you want in a custom description.
|
|||
|
||||
Markdown is rendered.
|
||||
"""
|
||||
|
||||
[extra.series_intro_templates]
|
||||
prev_only = "Welcome back to $SERIES_HTML_LINK! This is article the $POSITION of $SERIES_PAGES_NUMBER, following $PREV_HTML_LINK."
|
||||
next_only = "Welcome to $SERIES_HTML_LINK! This is the $POSITION article in a $SERIES_PAGES_NUMBER-part series."
|
||||
middle = "Welcome to the $POSITION of $SERIES_PAGES_NUMBER articles in $SERIES_HTML_LINK. We previously covered $PREV_HTML_LINK."
|
||||
default = "This article is part $SERIES_PAGE_INDEX of $SERIES_PAGES_NUMBER in the $SERIES_HTML_LINK series."
|
||||
|
||||
[extra.series_outro_templates]
|
||||
prev_only = "Check out the previous post in the $SERIES_HTML_LINK series: [$PREV_TITLE]($PREV_PERMALINK)."
|
||||
next_only = "This is the start of the [series]($SERIES_PERMALINK). Continue with $NEXT_HTML_LINK!"
|
||||
middle = "Previously: $PREV_HTML_LINK. Up next: $NEXT_HTML_LINK."
|
||||
default = "This article is part of the $SERIES_HTML_LINK 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.
|
||||
|
|
|
@ -14,140 +14,149 @@ Parameters:
|
|||
- `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 -%}
|
||||
{# 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 introduction #}
|
||||
{%- set series_page_introduction = series_section.extra.series_page_introduction | default(value="") -%}
|
||||
{%- set series_page_introduction = series_page_introduction | 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_introduction = series_page_introduction | 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) -%}
|
||||
|
||||
{# Replace introduction custom placeholders #}
|
||||
{%- if series_section.extra.series_page_introduction_placeholders is defined -%}
|
||||
{%- set missing_vars = [] -%}
|
||||
{%- for placeholder in series_section.extra.series_page_introduction_placeholders -%}
|
||||
{%- if placeholder in series_page_introduction -%}
|
||||
{# Attempt to retrieve the corresponding variable by trimming the $ sign and converting to lowercase #}
|
||||
{%- set var_name = placeholder | replace(from="$", to="") | lower -%}
|
||||
{%- if page.extra.series_page_introduction_variables[var_name] -%}
|
||||
{%- set_global series_page_introduction = series_page_introduction | replace(from=placeholder, to=page.extra.series_page_introduction_variables[var_name]) -%}
|
||||
{%- else -%}
|
||||
{# Append the variable name to the list of missing variables #}
|
||||
{% set_global missing_vars = missing_vars | concat(with=var_name) -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- if missing_vars | length > 0 -%}
|
||||
{%- set missing_vars_str = missing_vars | join(sep=", ") -%}
|
||||
{{ throw(message="ERROR: The following variables are included in this page's series introduction (`series_page_introduction_placeholders`) but have not been set in the `series_page_introduction_variables` of this page: " ~ missing_vars_str) }}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
|
||||
{%- if series_page_introduction | length > 0 -%}
|
||||
<section class="series-page-introduction">
|
||||
{{ series_page_introduction | markdown | safe }}
|
||||
</section>
|
||||
{%- endif -%}
|
||||
{% macro process_series_template(template_type, page, series_section, series_ordered_pages, language_strings) %}
|
||||
{%- if "series" in series_section.extra and series_section.extra.series -%}
|
||||
{# 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>' -%}
|
||||
{# Build series pages list #}
|
||||
{%- set series_pages_list = [] -%}
|
||||
{%- for series_page in series_ordered_pages -%}
|
||||
{%- if series_page.relative_path == page.relative_path -%}
|
||||
{%- 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_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>' -%}
|
||||
|
||||
{# Get page position and navigation info #}
|
||||
{%- set series_pages_number = 0 -%}
|
||||
{%- set series_page_index = 0 -%}
|
||||
{%- set first_page = series_ordered_pages | first -%}
|
||||
{%- set is_found = false -%}
|
||||
|
||||
{%- 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_global is_found = true -%}
|
||||
{%- else -%}
|
||||
{%- if not is_found -%}
|
||||
{%- set_global prev_page = series_page -%}
|
||||
{%- elif not next_page is defined -%}
|
||||
{%- set_global next_page = series_page -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
|
||||
{# Determine template to use based on available navigation #}
|
||||
{%- set position = "middle" -%}
|
||||
{%- if prev_page is defined and not next_page is defined -%}
|
||||
{%- set_global position = "prev_only" -%}
|
||||
{%- elif next_page is defined and not prev_page is defined -%}
|
||||
{%- set_global position = "next_only" -%}
|
||||
{%- endif -%}
|
||||
|
||||
{# Get template from config #}
|
||||
{%- set templates_key = "series_" ~ template_type ~ "_templates" -%}
|
||||
{%- set template = "" -%}
|
||||
{%- if series_section.extra[templates_key] is defined -%}
|
||||
{%- if series_section.extra[templates_key][position] is defined -%}
|
||||
{%- set_global template = series_section.extra[templates_key][position] -%}
|
||||
{%- elif series_section.extra[templates_key].default is defined -%}
|
||||
{%- set_global template = series_section.extra[templates_key].default -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
|
||||
{# Prepare navigation variables #}
|
||||
{%- if prev_page is defined -%}
|
||||
{%- set prev_title = prev_page.title -%}
|
||||
{%- set prev_permalink = prev_page.permalink -%}
|
||||
{%- set prev_html_link = '<a href="' ~ prev_page.permalink ~ '" aria_label="' ~ prev_page.title ~ '">' ~ prev_page.title ~ '</a>' -%}
|
||||
{%- set prev_description = prev_page.description | default(value="") -%}
|
||||
{%- endif -%}
|
||||
{%- if next_page is defined -%}
|
||||
{%- set next_title = next_page.title -%}
|
||||
{%- set next_permalink = next_page.permalink -%}
|
||||
{%- set next_html_link = '<a href="' ~ next_page.permalink ~ '" aria_label="' ~ next_page.title ~ '">' ~ next_page.title ~ '</a>' -%}
|
||||
{%- set next_description = next_page.description | default(value="") -%}
|
||||
{%- endif -%}
|
||||
|
||||
{# Replace standard variables #}
|
||||
{%- set template = template
|
||||
| replace(from="$SERIES_TITLE", to=series_title)
|
||||
| replace(from="$SERIES_PERMALINK", to=series_permalink)
|
||||
| replace(from="$SERIES_HTML_LINK", to=series_html_link)
|
||||
| replace(from="$FIRST_TITLE", to=first_page.title)
|
||||
| replace(from="$FIRST_HTML_LINK", to='<a href="' ~ first_page.permalink ~ '">' ~ first_page.title ~ '</a>')
|
||||
| replace(from="$SERIES_PAGES_NUMBER", to=series_pages_number | as_str)
|
||||
| replace(from="$SERIES_PAGE_INDEX", to=series_page_index | as_str)
|
||||
| replace(from="$SERIES_PAGES_OLIST", to=series_pages_ordered_list)
|
||||
| replace(from="$SERIES_PAGES_ULIST", to=series_pages_unordered_list)
|
||||
-%}
|
||||
|
||||
{# Replace navigation variables if they exist #}
|
||||
{%- if prev_page is defined -%}
|
||||
{%- set template = template
|
||||
| replace(from="$PREV_TITLE", to=prev_title)
|
||||
| replace(from="$PREV_PERMALINK", to=prev_permalink)
|
||||
| replace(from="$PREV_HTML_LINK", to=prev_html_link)
|
||||
| replace(from="$PREV_DESCRIPTION", to=prev_description)
|
||||
-%}
|
||||
{%- endif -%}
|
||||
|
||||
{%- if next_page is defined -%}
|
||||
{%- set template = template
|
||||
| replace(from="$NEXT_TITLE", to=next_title)
|
||||
| replace(from="$NEXT_PERMALINK", to=next_permalink)
|
||||
| replace(from="$NEXT_HTML_LINK", to=next_html_link)
|
||||
| replace(from="$NEXT_DESCRIPTION", to=next_description)
|
||||
-%}
|
||||
{%- endif -%}
|
||||
|
||||
{# Custom placeholders #}
|
||||
{%- if series_section.extra.series_template_placeholders is defined -%}
|
||||
{%- set missing_vars = [] -%}
|
||||
{%- for placeholder in series_section.extra.series_template_placeholders -%}
|
||||
{%- if placeholder in template -%}
|
||||
{%- set var_name = placeholder | replace(from="$", to="") | lower -%}
|
||||
{%- if page.extra.series_template_variables is defined and page.extra.series_template_variables[var_name] is defined -%}
|
||||
{%- set_global template = template | replace(from=placeholder, to=page.extra.series_template_variables[var_name]) -%}
|
||||
{%- else -%}
|
||||
{%- set_global missing_vars = missing_vars | concat(with=var_name) -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- if missing_vars | length > 0 -%}
|
||||
{%- set missing_vars_str = missing_vars | join(sep=", ") -%}
|
||||
{{ throw(message="ERROR: The following variables are included in this page's series templates (`series_template_placeholders`) but have not been set in the `series_template_variables` of this page: " ~ missing_vars_str) }}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
|
||||
{# Output the processed template if not empty #}
|
||||
{%- if template | length > 0 -%}
|
||||
<section class="series-page-{{ template_type }}">
|
||||
{{ template | markdown | safe }}
|
||||
</section>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{% endmacro %}
|
||||
|
||||
{#
|
||||
Computes the series navigation 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_navigation(page, series_section, series_ordered_pages, language_strings) %}
|
||||
{%- if macros_settings::evaluate_setting_priority(setting="show_previous_next_series_article_links", page=page, default_global_value=false) == "true" -%}
|
||||
{%- if series_ordered_pages | length > 1 -%}
|
||||
{% set next_series_label = macros_translate::translate(key="next_series", default="Next (series)", language_strings=language_strings) %}
|
||||
{% set prev_series_label = macros_translate::translate(key="prev_series", default="Prev (series)", language_strings=language_strings) %}
|
||||
{% set is_previous = true %}
|
||||
{% set is_next = false %}
|
||||
{%- for series_page in series_ordered_pages -%}
|
||||
{%- if series_page.relative_path == page.relative_path -%}
|
||||
{%- set_global is_previous = false -%}
|
||||
{%- set_global is_next = true -%}
|
||||
{%- else -%}
|
||||
{%- if is_previous -%}
|
||||
{%- set_global prev_series_page = series_page -%}
|
||||
{%- endif -%}
|
||||
{%- if is_next -%}
|
||||
{%- set_global next_series_page = series_page -%}
|
||||
{%- set_global is_next = false-%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{% if macros_settings::evaluate_setting_priority(setting="invert_previous_next_article_links", page=page, default_global_value=true) == "true" %}
|
||||
{% if prev_series_page %}
|
||||
{% set left_series_link = prev_series_page.permalink %}
|
||||
{% set left_series_label = prev_series_label %}
|
||||
{% set left_series_title = prev_series_page.title %}
|
||||
{% endif %}
|
||||
{% if next_series_page %}
|
||||
{% set right_series_link = next_series_page.permalink %}
|
||||
{% set right_series_label = next_series_label %}
|
||||
{% set right_series_title = next_series_page.title %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if next_series_page %}
|
||||
{% set left_series_link = next_series_page.permalink %}
|
||||
{% set left_series_label = next_series_label %}
|
||||
{% set left_series_title = next_series_page.title %}
|
||||
{% endif %}
|
||||
{% if prev_series_page %}
|
||||
{% set right_series_link = prev_series_page.permalink %}
|
||||
{% set right_series_label = prev_series_label %}
|
||||
{% set right_series_title = prev_series_page.title %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if macros_settings::evaluate_setting_priority(setting="previous_next_article_links_full_width", page=page, default_global_value=true) == "true" %}
|
||||
{%- set full_width_class = "full-width" -%}
|
||||
{% endif %}
|
||||
<nav class="{{ full_width_class | default(value="") }} series-article-navigation">
|
||||
<div>
|
||||
{%- if left_series_link and left_series_label and left_series_title -%}
|
||||
<a href="{{ left_series_link | safe }}" aria-label="{{ left_series_label }}" aria-describedby="left_series_title"><span class="arrow">←</span> {{ left_series_label }}</a>
|
||||
<p aria-hidden="true" id="left_series_title">{{ left_series_title | truncate(length=100, end="…") }}</p>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
<div>
|
||||
{%- if right_series_link and right_series_label and right_series_title -%}
|
||||
<a href="{{ right_series_link | safe }}" aria-label="{{ right_series_label }}" aria-describedby="right_series_title">{{ right_series_label }} <span class="arrow">→</span></a>
|
||||
<p aria-hidden="true" id="right_series_title">{{ right_series_title | truncate(length=100, end="…") }}</p>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</nav>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{# Macro for series introduction #}
|
||||
{% macro get_introduction(page, series_section, series_ordered_pages, language_strings) %}
|
||||
{{ macros_series_page::process_series_template(template_type="intro", page=page, series_section=series_section, series_ordered_pages=series_ordered_pages, language_strings=language_strings) }}
|
||||
{% endmacro %}
|
||||
|
||||
{# Macro for series outro #}
|
||||
{% macro get_outro(page, series_section, series_ordered_pages, language_strings) %}
|
||||
{{ macros_series_page::process_series_template(template_type="outro", page=page, series_section=series_section, series_ordered_pages=series_ordered_pages, language_strings=language_strings) }}
|
||||
{% endmacro %}
|
||||
|
|
|
@ -172,7 +172,7 @@ Current section extra: {% if current_section %}{{ current_section.extra | json_e
|
|||
{%- set formatted_date = macros_format_date::format_date(date=page.updated, short=true, language_strings=language_strings) -%}
|
||||
{%- set updated_str = last_updated_str | replace(from="$DATE", to=formatted_date) -%}
|
||||
</ul><ul class="meta last-updated"><li>{{ updated_str }}</li>
|
||||
{# Show link to remote changes if enabled #}
|
||||
{#- Show link to remote changes if enabled -#}
|
||||
{% if config.extra.remote_repository_url and macros_settings::evaluate_setting_priority(setting="show_remote_changes", page=page, default_global_value=true) == "true" %}
|
||||
{%- if previous_visible -%}{{ separator }} {%- endif -%}
|
||||
<li><a href="{% include "partials/history_url.html" %}" {{ blank_target }} rel="{{ rel_attributes }}">{{ macros_translate::translate(key="see_changes", default="See changes", language_strings=language_strings) }}<small> <span class="arrow-corner">↗</span></small></a></li>
|
||||
|
@ -180,10 +180,10 @@ 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. #}
|
||||
{#- 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) -%}
|
||||
|
@ -191,7 +191,7 @@ Current section extra: {% if current_section %}{{ current_section.extra | json_e
|
|||
{%- 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 #}
|
||||
{#- 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 -%}
|
||||
|
@ -207,10 +207,6 @@ Current section extra: {% if current_section %}{{ current_section.extra | json_e
|
|||
{%- 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>
|
||||
|
@ -223,18 +219,48 @@ Current section extra: {% if current_section %}{{ current_section.extra | json_e
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Optional table of contents below the header #}
|
||||
{#- Optional table of contents below the header -#}
|
||||
{% if page.toc and macros_settings::evaluate_setting_priority(setting="toc", page=page, default_global_value=false) == "true" %}
|
||||
{{ macros_toc::toc(page=page, header=true, language_strings=language_strings) }}
|
||||
{% endif %}
|
||||
|
||||
<section class="body">
|
||||
{# The replace pattern is used to enable arbitrary locations for the Table of Contents #}
|
||||
{# This is Philipp Oppermann's workaround: https://github.com/getzola/zola/issues/584#issuecomment-474329637 #}
|
||||
{{ page.content | replace(from="<!-- toc -->", to=macros_toc::toc(page=page, header=false, language_strings=language_strings)) | safe }}
|
||||
{#- Replace series_intro placeholder -#}
|
||||
{%- set content_with_intro = page.content -%}
|
||||
{%- if "<!-- series_intro -->" in page.content -%}
|
||||
{%- set series_intro_html = macros_series_page::get_introduction(page=page, series_section=series_section, series_ordered_pages=series_ordered_pages, language_strings=language_strings) -%}
|
||||
{%- set content_with_intro = content_with_intro | replace(from="<!-- series_intro -->", to=series_intro_html) -%}
|
||||
{%- elif series_section -%}
|
||||
{%- set series_intro_html = macros_series_page::get_introduction(page=page, series_section=series_section, series_ordered_pages=series_ordered_pages, language_strings=language_strings) -%}
|
||||
{%- set content_with_intro = series_intro_html ~ content_with_intro -%}
|
||||
{%- endif -%}
|
||||
|
||||
{#- Handle series_outro placeholder -#}
|
||||
{%- set processed_content = content_with_intro -%}
|
||||
{%- if "<!-- series_outro -->" in content_with_intro -%}
|
||||
{%- set series_outro_html = macros_series_page::get_outro(page=page, series_section=series_section, series_ordered_pages=series_ordered_pages, language_strings=language_strings) -%}
|
||||
{%- set processed_content = processed_content | replace(from="<!-- series_outro -->", to=series_outro_html) -%}
|
||||
{%- elif series_section -%}
|
||||
{%- set series_outro_html = macros_series_page::get_outro(page=page, series_section=series_section, series_ordered_pages=series_ordered_pages, language_strings=language_strings) -%}
|
||||
{#- We want the outro at the end of the article, but before footnote definitions -#}
|
||||
{%- set footnotes_marker = '<hr><ol class="footnotes-list">' -%}
|
||||
{%- if footnotes_marker in content_with_intro -%}
|
||||
{%- set content_sections = processed_content | split(pat=footnotes_marker) -%}
|
||||
{%- set main_content = content_sections | first -%}
|
||||
{%- set footnotes_content = content_sections | slice(start=1) | join(sep=footnotes_marker) -%}
|
||||
{%- set processed_content = main_content ~ series_outro_html ~ footnotes_marker ~ footnotes_content -%}
|
||||
{%- else -%}
|
||||
{%- set processed_content = processed_content ~ series_outro_html -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
|
||||
{#- Replace TOC and render final content -#}
|
||||
{#- The replace pattern is used to enable arbitrary locations for the Table of Contents -#}
|
||||
{#- This is Philipp Oppermann's workaround: https://github.com/getzola/zola/issues/584#issuecomment-474329637 -#}
|
||||
{{ processed_content | replace(from="<!-- toc -->", to=macros_toc::toc(page=page, header=false, language_strings=language_strings)) | safe }}
|
||||
</section>
|
||||
|
||||
{# Check if comments are enabled, checking that they are not disabled on the specific page #}
|
||||
{#- Check if comments are enabled, checking that they are not disabled on the specific page -#}
|
||||
{% set systems = ["giscus", "utterances", "hyvortalk", "isso"] %}
|
||||
{% set enabled_systems = 0 %}
|
||||
{% set comment_system = "" %}
|
||||
|
@ -250,9 +276,6 @@ Current section extra: {% if current_section %}{{ current_section.extra | json_e
|
|||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if series_section %}
|
||||
{{ macros_series_page::get_navigation(page=page, series_section=series_section, series_ordered_pages=series_ordered_pages, language_strings=language_strings)}}
|
||||
{%- endif -%}
|
||||
{% if macros_settings::evaluate_setting_priority(setting="show_previous_next_article_links", page=page, default_global_value=true) == "true" %}
|
||||
{%- if page.lower or page.higher -%}
|
||||
{% set next_label = macros_translate::translate(key="next", default="Next", language_strings=language_strings) %}
|
||||
|
@ -300,12 +323,12 @@ Current section extra: {% if current_section %}{{ current_section.extra | json_e
|
|||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
|
||||
{# Ensure only one comment system is enabled #}
|
||||
{#- Ensure only one comment system is enabled -#}
|
||||
{% if enabled_systems > 1 %}
|
||||
{{ throw(message="ERROR: Multiple comment systems have been enabled for the same page. Check your config.toml and individual page settings to ensure only one comment system is activated at a time.") }}
|
||||
{% endif %}
|
||||
|
||||
{# Comments #}
|
||||
{#- Comments -#}
|
||||
{% if comment_system %}
|
||||
{% include "partials/comments.html" %}
|
||||
{% endif %}
|
||||
|
|
|
@ -122,7 +122,7 @@ post_listing_date = "date"
|
|||
# Determines if indexes should be increasing (false) or decreasing (true) in series' posts list.
|
||||
# It has only effect if the section uses indexes metadata (which is only the case for series as of now).
|
||||
# Can be set at section levels, following the hierarchy: section > config. See: https://welpo.github.io/tabi/blog/mastering-tabi-settings/#settings-hierarchy
|
||||
post_listing_index_reversed = false # Defaults to false.
|
||||
post_listing_index_reversed = false # Defaults to false.
|
||||
|
||||
# DEPRECATED!
|
||||
# Use Zola's built-in `bottom_footnotes = true` in the [markdown] section instead. (Available since v0.19.0)
|
||||
|
@ -148,10 +148,6 @@ serve_local_mermaid = true
|
|||
# Can be set at page or section levels, following the hierarchy: page > section > config. See: https://welpo.github.io/tabi/blog/mastering-tabi-settings/#settings-hierarchy
|
||||
show_previous_next_article_links = false
|
||||
|
||||
# Show links to previous and next series articles at the bottom of posts which is part of a series.
|
||||
# Can be set at page or section levels, following the hierarchy: page > section > config. See: https://welpo.github.io/tabi/blog/mastering-tabi-settings/#settings-hierarchy
|
||||
show_previous_next_series_article_links = false
|
||||
|
||||
# Invert order of the links to previous and next articles at the bottom of posts.
|
||||
# By default, next articles are on the left side of the page and previous articles are on the right side.
|
||||
# To reverse the order (next articles on the right and previous articles on the left), set it to true.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue