Upgrade your tabi site to Zola 0.23
Zola 0.23 breaks many things; so does tabi 5.0.0. Zola 0.23.0 changed many things, mostly due to the upgrade to Tera 2. Since this required users making changes, I’ve taken the opportunity to deprecate existing settings that only existed for backwards compatibility. This documents aims to facilitate the transition. tabi requires Zola 0.23.6 or newer. Check the version used locally, in CI, and for deployment: If you must stay on Zola older than 0.23.0, pin tabi to Existing clone: Submodule: The parent repository records the submodule commit, not the tag name. For a new clone: If you set Common replacements are Find inline shortcode calls: Find block shortcode calls: Each hit is a file, line number, and the call. Two kinds show up: If you wrapped examples in List custom shortcodes and macros: Anything listed is yours, not tabi’s, and needs porting to Check the config for retired settings: Move highlighting settings from For separate themes: tabi requires The root Inline calls lose parentheses and commas: Block calls use named closing tags: Wrap expressions, booleans, numbers, arrays, and maps in braces. Component parameters are explicit by default. Prefix ambient context parameters with Move site-local templates from Use ordinary parameters for the component’s inputs and implicit parameters for ambient values such as Markdown is templated before fenced code is rendered. Wrap literal examples in Custom heading IDs do not need raw blocks: Use Site overrides under Undefined access is stricter. Use optional chaining such as See the Tera migration guide for the complete language changes.zola --versionv4.2.0, the final compatible release.git -C themes/tabi fetch --tags
git -C themes/tabi checkout --detach v4.2.0
git -C themes/tabi describe --tags --exact-matchgit submodule update --init themes/tabi
git -C themes/tabi fetch --tags
git -C themes/tabi checkout --detach v4.2.0
git add themes/tabi
git diff --cached --submodule=log -- themes/tabi
git commit -m "Pin tabi v4.2.0 for pre-0.23 Zola"git clone --branch v4.2.0 --depth 1 https://github.com/welpo/tabi.git themes/tabi Table of Contents
Remove retired settings
footnote_backlinks: use [markdown].bottom_footnotes = true.add_src_to_code_block: use named code fences and code_block_name_links.[extra].index_format: move it to [search] and each enabled language search table.translate_copyright and translated_copyright: use copyright_translations. Update date formats
long_date_format, short_date_format, archive_date_format, or date_formats, rewrite each value using UTS-35 patterns. Strftime % directives fail when tabi applies the language locale.# Before
long_date_format = "%d %B %Y"
# After
long_date_format = "dd MMMM y"%-d → d, %d → dd, %b → MMM, %B → MMMM, and %Y → y. Quote literal text: d 'de' MMMM 'de' y. Find what needs changing
grep -rEn --include='*.md' '[{][{][[:space:]]*[A-Za-z_][A-Za-z0-9_]*[[:space:]]*[(]' contentgrep -rEn --include='*.md' '[{]%[[:space:]]*[A-Za-z_][A-Za-z0-9_]*[[:space:]]*[(]' contentadmonition, toc, or dual_theme_image. Convert these to component syntax, as shown below.get_url, resize_image, or get_taxonomy_url. These still work in 0.23. Leave them alone.{% raw %}, those hits are literal text. Leave them too.ls templates/shortcodes templates/macrostemplates/components/.grep -En 'footnote_backlinks|add_src_to_code_block|translate_copyright|translated_copyright|index_format|highlight_code|highlight_theme' config.toml Update syntax highlighting
[markdown] to [markdown.highlighting]:[markdown]
smart_punctuation = true
[markdown.highlighting]
theme = "catppuccin-frappe"
style = "class"
error_on_missing_language = true[markdown.highlighting]
light_theme = "catppuccin-latte"
dark_theme = "catppuccin-frappe"
style = "class"
error_on_missing_language = truestyle = "class". Zola generates giallo.css, or giallo-light.css and giallo-dark.css. Configure multilingual search
[search] table configures the default language. Every other language with build_search_index = true needs its own table:build_search_index = true
[search]
include_title = true
include_description = true
include_path = true
include_content = true
index_format = "elasticlunr_json"
[languages.es]
title = "Mi sitio"
build_search_index = true
[languages.es.search]
include_title = true
include_description = true
include_path = true
include_content = true
index_format = "elasticlunr_json" Convert shortcodes to components
-{{ admonition(type="tip", text="Stay hydrated") }}
+{{< admonition type="tip" text="Stay hydrated" />}}-{% admonition(type="tip") %}
+{% <admonition type="tip"> %}
Stay hydrated.
-{% end %}
+{% </admonition> %}@ in the component definition so Tera resolves them from the caller:{% component post_language(@lang: string) %}
{{ lang }}
{% endcomponent post_language %}{{< dual_theme_image light_src="light.webp" dark_src="dark.webp" full_width={true} />}}
{{< multilingual_quote original="Hola" translated="Hello" />}}
{{< iine />}} Move custom shortcodes
templates/shortcodes/ to templates/components/ and define a component. This example is adapted from a tabi consumer:{% component youtube(id: string, class = "", playlist = "", autoplay = false) %}
<div{% if class %} class="{{ class }}"{% endif %}>
<iframe src="https://www.youtube-nocookie.com/embed/{{ id }}{% if playlist %}?list={{ playlist }}{% if autoplay %}&autoplay=1{% endif %}{% elif autoplay %}?autoplay=1{% endif %}" allowfullscreen></iframe>
</div>
{% endcomponent youtube %}{{< youtube id="dQw4w9WgXcQ" class="video" autoplay={true} />}}lang, config, or page. An implicit value can still be overridden explicitly at the call site. Protect literal examples
{% raw %} and {% endraw %} in the source file.## Deployment checks {#deployment-checks}skip_content_templating only when the complete file should bypass templating. Review custom templates
templates/ are not updated with the theme.Old Current macros and {% import %}components items | concat(with=item)[...items, item]items | slice(start=1)items[1:]value | as_strvalue | strtrim_start_matches / trim_end_matchestrim_start / trim_enditem.0item[0]is starting_with("http")is starting_with(pat="http")is iterable for arraysis arrayget_taxonomy_url(..., name=term)get_taxonomy_url(..., term=term){% include "x" ignore missing %}include an existing default file page?.extra?.setting, and guard explicit null values before applying filters. default(value=...) handles undefined values, not null values.get_page and get_section take a canonical path plus lang. Component arguments use string literals or braced expressions; page is shorthand for page={page}. Expected output differences
#fn-* and #fr-* fragments.z-*, or z-l-*/z-d-*, token classes.hreflang order can change; destinations should not.