feat(config): add global nav.toc setting with frontmatter override

- Add toc: bool to [nav] config section (default: false)
- Frontmatter toc: true/false overrides global config
- If frontmatter toc is not specified, falls back to config.nav.toc
- Enable nav.toc = true in docs/site.toml for global TOC
This commit is contained in:
Timothy DeHerrera
2026-02-01 09:42:00 -07:00
parent dcc98dccef
commit c8c2506e16
5 changed files with 23 additions and 10 deletions

View File

@@ -2,7 +2,6 @@
title: Tera Templates
description: Customizable templates without recompilation
weight: 1
toc: true
---
sukr uses [Tera](https://tera.netlify.app/), a Jinja2-like templating engine. Templates are loaded at runtime, so you can modify them without recompiling sukr.

View File

@@ -10,3 +10,4 @@ templates = "templates"
[nav]
nested = true
toc = true

View File

@@ -28,6 +28,9 @@ pub struct SiteConfig {
pub struct NavConfig {
/// Whether to display nested navigation (default: false).
pub nested: bool,
/// Enable table of contents (anchor nav) globally (default: false).
/// Can be overridden per-page via frontmatter toc field.
pub toc: bool,
}
/// Path configuration with sensible defaults.

View File

@@ -159,7 +159,7 @@ fn run(config_path: &Path) -> Result<()> {
let page_path = format!("/{}/index.html", section.name);
let item_contexts: Vec<_> = items
.iter()
.map(|c| ContentContext::from_content(c, &content_dir))
.map(|c| ContentContext::from_content(c, &content_dir, &config))
.collect();
let html = engine.render_section(
&section.index,

View File

@@ -45,7 +45,10 @@ impl TemplateEngine {
) -> Result<String> {
let mut ctx = self.base_context(page_path, config, nav);
ctx.insert("title", &content.frontmatter.title);
ctx.insert("page", &FrontmatterContext::from(&content.frontmatter));
ctx.insert(
"page",
&FrontmatterContext::new(&content.frontmatter, config),
);
ctx.insert("content", html_body);
ctx.insert("anchors", anchors);
self.render("page.html", &ctx)
@@ -68,7 +71,10 @@ impl TemplateEngine {
.unwrap_or("content/default.html");
let mut ctx = self.base_context(page_path, config, nav);
ctx.insert("title", &content.frontmatter.title);
ctx.insert("page", &FrontmatterContext::from(&content.frontmatter));
ctx.insert(
"page",
&FrontmatterContext::new(&content.frontmatter, config),
);
ctx.insert("content", html_body);
ctx.insert("anchors", anchors);
self.render(template, &ctx)
@@ -88,7 +94,10 @@ impl TemplateEngine {
let mut ctx = self.base_context(page_path, config, nav);
ctx.insert("title", &section.frontmatter.title);
ctx.insert("section", &FrontmatterContext::from(&section.frontmatter));
ctx.insert(
"section",
&FrontmatterContext::new(&section.frontmatter, config),
);
ctx.insert("items", items);
self.render(&template, &ctx)
}
@@ -154,8 +163,9 @@ pub struct FrontmatterContext {
pub toc: bool,
}
impl From<&crate::content::Frontmatter> for FrontmatterContext {
fn from(fm: &crate::content::Frontmatter) -> Self {
impl FrontmatterContext {
/// Create context from frontmatter with config fallback for toc.
pub fn new(fm: &crate::content::Frontmatter, config: &SiteConfig) -> Self {
Self {
title: fm.title.clone(),
description: fm.description.clone(),
@@ -163,7 +173,7 @@ impl From<&crate::content::Frontmatter> for FrontmatterContext {
tags: fm.tags.clone(),
weight: fm.weight,
link_to: fm.link_to.clone(),
toc: fm.toc.unwrap_or(false),
toc: fm.toc.unwrap_or(config.nav.toc),
}
}
}
@@ -178,9 +188,9 @@ pub struct ContentContext {
}
impl ContentContext {
pub fn from_content(content: &Content, content_dir: &Path) -> Self {
pub fn from_content(content: &Content, content_dir: &Path, config: &SiteConfig) -> Self {
Self {
frontmatter: FrontmatterContext::from(&content.frontmatter),
frontmatter: FrontmatterContext::new(&content.frontmatter, config),
body: content.body.clone(),
slug: content.slug.clone(),
path: format!("/{}", content.output_path(content_dir).display()),